2009-08-13 10 views
10

Po odczytaniu niektórych plików JPG kolory są spłaszczone. Oto prosty przykład, który czyta jpg i po prostu zapisuje ten sam obraz do innego pliku.Dlaczego Java ImageIO spłaszcza kolory 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"); 
     } 
    } 
} 

Jeśli spróbujesz to się na przykład http://www.flickr.com/photos/visualpanic/233508614/sizes/l/, kolory obrazu docelowego różnią się od pliku źródłowego. Dlaczego? Jak to naprawić?

Próbowano również zapisywać obraz jako png, ale kolory są również bezbarwne (więc zakładając, że informacje o kolorach nie są poprawnie czytane).

+0

Czy dowiedzieć się, jak zachować profil kolorów? Mam ten sam problem. –

Odpowiedz

10

Może to być kilka powodów.

  1. Dane koloru JPEG są często zapisywane jako YCrCb zamiast RGB, chociaż konwersje powinny być w większości niezauważalne.
  2. JPEG często ma osadzony profil kolorów, ale wiele aplikacji tego nie rozumie i po prostu go ignoruje (w takim przypadku w pliku wyjściowym może brakować profilu kolorów).
  3. Wartość Gamma może zostać zresetowana lub utracona po tym, jak Java ją zmapuje.

Nie wypróbowałem twojego przykładu ... czy mógłbyś opublikować zarówno przed, jak i po plikach? Bez faktycznego sprawdzania pliku wynikowego trudno jest stwierdzić, czy istnieją dodatkowe dane, czy nie.

Edytuj: Tak, jasne jest, że oryginalne i przekonwertowane obrazy mają różne profile kolorów. Java usunęła oryginalny profil koloru i zamiast niego użył generycznego sRGB. Wyglądają tak samo w Windowsie z Firefoksem i innymi programami, ponieważ te programy nie używają profilu kolorów podczas renderowania. Jednak na twoim Macu Mac faktycznie obsługuje te profile kolorów (debata nad Macami dla grafiki, itp.) I dlatego renderują inaczej. Nie mam pod ręką komputera Mac, ale podejrzewam, że jeśli otworzysz pliki w Photoshopie na dowolnej platformie, zobaczysz różnicę.

+0

OK, tutaj są pliki przed i po. http://terokinnunen.jalbum.net/Colortest/orig.jpg http://terokinnunen.jalbum.net/Colortest/converted-jpg.jpg próbował także zapisywanie jako png, nadal mdłe http: // terokinnunen .jalbum.net/Colortest/convert-png.png – ketorin

+0

Interesujące: dla mnie (Ubuntu 9.04, Firefox 3.5/Gimp) oryginalny i skonwertowany wygląd prawie tak samo (artefakty JPEG modulu). Jedyną różnicą, jaką mogę znaleźć w GIMP, jest to, że oryginał określa "sRGB IEC61966-2.1" jako przestrzeń kolorów, a przekonwertowany ma "wbudowane sRGB". –

+0

Oni robią? Rzeczywiście interesujące. Dla mnie (Mac i Safari lub Firefox) kolory różnią się znacznie w nawróconych. Sprawdziłem również w systemie Windows i ku mojemu zdziwieniu również wyglądają one prawie tak samo, tylko niewielka różnica. – ketorin

0

jpeg to format stratny. Po wczytaniu java przechowuje je jako surowy format podobny do BMP. Następnie jest ponownie zapisywany, powodując utratę danych. Ponadto, nie ma zbyt dużej kontroli nad jakością, jak w przypadku używania czegoś takiego jak GIMP.

Być może warto skorzystać z innych interfejsów API, takich jak Image Magick, aby zapewnić większą kontrolę nad jakością.

+2

Nieistotne. OP wskazuje na znaczący problem z profilem kolorów, wykraczający poza zwykłą dekompresję. – erjiang

0

JPEG to format lossy.

Oznacza to, że jeśli otworzysz plik i zapiszesz go ponownie, stracisz trochę informacji, chyba że podejmiesz bardzo konkretne kroki, aby nie stracić (w takim przypadku możliwe manipulacje są bardzo ograniczone).

Dodatkowo ImageIO.write() prawdopodobnie używa niektórych domyślnych ustawień jakości do zapisywania plików JPEG, które mogą być niższe niż oryginały, co może prowadzić do dodatkowej utraty jakości.

Spróbuj zapisać do pliku PNG, a zobaczysz, że będzie wyglądać tak samo jak źródło.

+0

Próbowałem zapisać do png, ale wygląda również nijako w kolorze, tak samo jak obraz zapisany w formacie jpg. Mam przeczucie, że kolory nie są nawet czytane poprawnie. – ketorin

+0

W takim przypadku problem może polegać na tym, że jakiś profil kolorów jest przechowywany na obrazie, którego Java nie odczytuje/nie interpretuje. –

2

Być może obraz źródłowy ma przypisany profil kolorów o szerszej gamie niż sRGB (np. Adobe RGB), a cykl ładowania/zapisywania nie chroni informacji o przestrzeni kolorów? Bez profilu kolorów, przeglądarka przyjmie sRGB, a skompresowana gama sprawi, że wszystko będzie wyglądać "blah".Jeśli masz produkt exiftool, to:

exiftool -ProfileDescription filename.jpg 

to szybki sposób na sprawdzenie profili kolorów na źródłowych i wyjściowych obrazach.

+0

Tak, może to być problem, w rzeczywistości brakuje profilu w plikach wyjściowych. Ten wątek wygląda obiecująco: http://forums.java.net/jive/thread.jspa?threadID=60631&tstart=0, zamierzam przyjrzeć się temu dalej. – ketorin

+0

Ups, to był niewłaściwy wątek: http://forums.java.net/jive/message.jspa?messageID=205964 – ketorin

0

Oto link z kodem źródłowym, który rozszerza się na interfejsie ImageIO - można zmieniać parametry jakościowe i kompresji przy zapisie obrazu .... http://www.universalwebservices.net/web-programming-resources/java/adjust-jpeg-image-compression-quality-when-saving-images-in-java

+0

To jest niejasne. Czy próbowałeś go z obrazem z pytania? Zasadniczo mówisz OP, aby * ponownie sprawdził dokumenty *. Przyjęta odpowiedź sugeruje, że ta odpowiedź nie rozwiąże problemów związanych z PO. – andr

Powiązane problemy