2009-08-13 26 views
10

Khi tôi đọc một số tệp JPG nhất định, màu sắc được làm phẳng. Đây là một ví dụ đơn giản mà đọc một jpg và chỉ viết cùng một hình ảnh cho một tập tin khác.Tại sao Java ImageIO làm phẳng các màu JPEG

import java.awt.image.BufferedImage; 
import java.io.File; 
import javax.imageio.ImageIO; 

public class JPegReadTest { 
    public static void main(String[] args) { 
     if (args.length == 2) { 
      try { 
       BufferedImage src = ImageIO.read(new File(args[0])); 
       ImageIO.write(src, "jpg", new File(args[1])); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } else { 
      System.err.println("Usage: java JPegReadTest src dest"); 
     } 
    } 
} 

Nếu bạn thử ví dụ này http://www.flickr.com/photos/visualpanic/233508614/sizes/l/, màu sắc của hình ảnh đích khác với tệp nguồn. Tại sao vậy? Làm thế nào để sửa chữa nó?

Cũng thử lưu hình ảnh dưới dạng png, nhưng màu sắc cũng nhạt nhẽo trong đó (vì vậy giả sử thông tin màu không được đọc chính xác).

+0

Bạn đã tìm ra cách để duy trì hồ sơ màu sắc? Tôi đang đối mặt với cùng một vấn đề –

Trả lời

10

Có thể là một vài lý do.

  1. Dữ liệu màu JPEG thường được lưu trữ dưới dạng YCrCb thay vì RGB, mặc dù chuyển đổi hầu như không đáng kể.
  2. JPEG thường có cấu hình màu được nhúng, nhưng nhiều ứng dụng không hiểu điều này và chỉ đơn giản bỏ qua nó (trong trường hợp này, tệp đầu ra của bạn có thể thiếu cấu hình màu).
  3. Giá trị Gamma có thể được đặt lại hoặc bị thiếu sau khi Java mang nó.

Tôi đã không thực sự thử ví dụ của bạn ... bạn có thể đăng cả trước và sau tệp không? Nếu không thực sự có thể kiểm tra tệp kết quả, thật khó để biết liệu dữ liệu bổ sung này có ở đó hay không.

Chỉnh sửa: Vâng, rõ ràng là ảnh gốc và hình ảnh được chuyển đổi của bạn có các cấu hình màu khác nhau. Java đã loại bỏ cấu hình màu gốc và sử dụng sRGB chung thay thế. Chúng giống với chúng ta trên Windows với Firefox và các chương trình khác nhau bởi vì các chương trình này không sử dụng profile màu khi renderer. Tuy nhiên, trên máy Mac của bạn, Mac thực sự hỗ trợ các cấu hình màu này (tranh luận cue trên Mac cho đồ họa, v.v.) và do đó chúng hiển thị khác nhau. Tôi không có một máy Mac tiện dụng, nhưng tôi nghi ngờ rằng nếu bạn mở các tập tin trong Photoshop trên bất kỳ nền tảng nào, bạn sẽ thấy sự khác biệt.

+0

Ok, đây là các tệp trước và sau. http://terokinnunen.jalbum.net/Colortest/orig.jpg http://terokinnunen.jalbum.net/Colortest/converted-jpg.jpg Cũng cố gắng lưu dưới dạng png, vẫn nhạt nhẽo http: // terokinnunen .jalbum.net/Colortest/conversion-png.png – ketorin

+0

Thú vị: đối với tôi (Ubuntu 9.04, Firefox 3.5/GIMP) bản gốc và được chuyển đổi trông khá giống nhau (các đồ tạo tác modulu JPEG). Sự khác biệt duy nhất mà tôi có thể tìm thấy với GIMP là bản gốc chỉ định "sRGB IEC61966-2.1" là không gian màu, trong khi chuyển đổi có "sRGB tích hợp sẵn". –

+0

Họ làm gì? Thật sự thú vị. Đối với tôi (Mac và Safari hoặc Firefox), màu sắc đáng chú ý là màu sắc khác nhau. Tôi cũng đã kiểm tra với Windows và sự ngạc nhiên của tôi họ cũng trông khá giống nhau, chỉ có một sự khác biệt nhỏ. – ketorin

0

jpeg là định dạng mất dữ liệu. Khi đọc, java lưu trữ nó như một định dạng thô giống như một BMP. Sau đó, nó được viết ra một lần nữa gây mất dữ liệu. Ngoài ra, không có nhiều kiểm soát về chất lượng như khi sử dụng một cái gì đó như GIMP.

Có thể xem xét sử dụng các API khác như Image Magick để cung cấp cho bạn nhiều quyền kiểm soát hơn đối với chất lượng.

+2

Không liên quan. OP đang chỉ ra một vấn đề quan trọng về màu sắc hơn là chỉ giải nén. – erjiang

0

JPEG là định dạng lossy. Điều này có nghĩa là nếu bạn mở một tệp và lưu lại, bạn sẽ mất một số thông tin trừ khi bạn thực hiện các bước rất cụ thể để không mất bất kỳ (trong trường hợp đó các thao tác có thể rất hạn chế).

Ngoài ra ImageIO.write() có thể sử dụng một số cài đặt chất lượng mặc định để lưu tệp JPEG, có thể thấp hơn bản gốc, điều này sẽ dẫn đến mất chất lượng bổ sung.

Thử lưu vào tệp PNG và bạn sẽ thấy rằng nó sẽ trông giống như nguồn.

+0

Tôi đã thử lưu thành png, nhưng nó cũng có màu nhạt, giống như hình ảnh đã lưu jpg. Tôi có linh cảm rằng các màu sắc thậm chí không đọc đúng. – ketorin

+0

Trong trường hợp đó, vấn đề có thể là một số cấu hình màu được lưu trữ trong hình ảnh mà Java không đọc/giải thích. –

2

Có lẽ hình ảnh nguồn của bạn có cấu hình màu được gán với một gam màu rộng hơn sRGB (như Adobe RGB) và chu kỳ tải/lưu của bạn không giữ được thông tin về không gian màu? Với không có hồ sơ màu sắc, người xem của bạn sẽ giả sử sRGB, và gam màu nén sẽ làm cho mọi thứ trông "blah".Nếu bạn có exiftool,

exiftool -ProfileDescription filename.jpg 

là cách nhanh chóng để xác minh cấu hình màu trên nguồn và hình ảnh đầu ra của bạn.

+0

Có, đây có thể là sự cố, hồ sơ thực sự bị thiếu trong các tệp đầu ra. Chuỗi này có vẻ đầy hứa hẹn: http://forums.java.net/jive/thread.jspa?threadID=60631&tstart=0, sẽ xem xét nó tiếp theo. – ketorin

+0

Rất tiếc, đó là chủ đề sai: http://forums.java.net/jive/message.jspa?messageID=205964 – ketorin

0

Dưới đây là một liên kết với mã nguồn mà mở rộng trên giao diện ImageIO - bạn có thể thay đổi các thông số chất lượng và nén khi viết một hình ảnh .... http://www.universalwebservices.net/web-programming-resources/java/adjust-jpeg-image-compression-quality-when-saving-images-in-java

+0

Điều này là mơ hồ. Bạn đã thử nó với hình ảnh từ câu hỏi chưa? Về cơ bản bạn đang nói OP để * kiểm tra các tài liệu * một lần nữa. Và câu trả lời được chấp nhận cho thấy câu trả lời này sẽ không giải quyết các vấn đề của OP. – andr

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