2012-05-14 5 views
8

Korzystam z platformy .NET (wypróbowałem 3.5 & 4.0), aby załadować plik .TIFF i zapisać go jako .PNG. Oczekuję dwóch kolejnych wywołań do metody Save() (przy użyciu tego samego pliku TIFF), aby utworzyć ten sam plik PNG. Wytworzone pliki są "czasami" inne.Metoda .NET Image.Save tworzy nieprzewijalne wyniki w 64-bitowym systemie Windows

C# kod pokazuje problem:

Image sourceToConvert = Bitmap.FromFile("c:\\tmp\\F1.tif"); 
sourceToConvert.Save("c:\\tmp\\F1_gen.png", ImageFormat.Png);   

for (int i = 0; i < 100; i++) 
{ 
    sourceToConvert = Bitmap.FromFile("c:\\tmp\\F1.tif"); 
    sourceToConvert.Save("c:\\tmp\\F1_regen.png", ImageFormat.Png); 

    if (!CompareFileBytes("c:\\tmp\\F1_gen.png", "c:\\tmp\\F1_regen.png")) 
     MessageBox.Show("Diff" + i);     
} 

PokaŜe 'diff w iteracji 8, 32, 33, 73 114, 155, 196 w systemie Windows 64, podczas gdy nie są wyświetlane żadne błędy na komputerach 32-bitowych. (Używam celu x86, z celem x64 jest gorzej: różnica w iteracji 12, 13, 14, 15, ...)

Czy istnieje sposób na uzyskanie powtarzalnego wyniku z Save()?

Próbka obrazu można znaleźć na tej FTP site

+0

Istnieją różne ustawienia, które idą do kompresji pliku i może być optymalizacja dla jakiegoś czynnika w czasie wykonywania. Na przykład coś takiego jak rozmiar słownika może wpływać na rozmiar skompresowanego wyjścia, ale nadal daje takie same zdekompresowane dane. Zatem twoje obrazy są wciąż takie same, ale mogły zostać zoptymalizowane nieco inaczej. Prawdopodobnie budowanie na 64-bitowe daje różne ustawienia pod maską. Możesz przyjrzeć się ustawieniom enkodera dla Save Overloads, ale nie widziałem niczego poza ręką, co spowodowałoby, że skompresowany wynik byłby deterministyczny. – mafafu

+0

Dzięki za komentarz. Ja też uważałem, że obrazy powinny być takie same w pamięci (tylko pliki .png różnią się). Ale posunąłem się nawet do napisania funkcji odczytywania obrazów jako BMP, konwertowania na tablicę bajtową i - są różne (chociaż wizualne obrazy nie różnią się). Odkryłem również, że problem występuje tylko w przypadku stosunkowo dużych obrazów (w moim przypadku około 2600 × 2600 pikseli). Próbowałem również z bibliotekami innych firm, takimi jak FreeImage - ten sam problem: deterministyczny na poziomie 32-bitowym, a nie na 64-bitowym. – werner

+1

Czy możesz zamieścić link do tego obrazu F1.tif pls? – avs099

Odpowiedz

2

Nie potrafię wyjaśnić, dlaczego tak się dzieje, ale wydaje się, że nie-deterministyczne finalizacja Image obiektów na gwincie finalizatora wpływa kodowanie obrazów na główny wątek. (Image realizuje IDisposable, więc należy zadzwonić Dispose na nim deterministycznie go oczyścić, gdy skończysz go używać;. W przeciwnym razie zostanie ona sfinalizowana w dowolnym momencie w przyszłości)

Gdybym zmienić przykładowy kod do dalszej, mam takie same wyniki z każdego zaproszenia do Save:

using (Image sourceToConvert = Bitmap.FromFile("c:\\tmp\\F1.tif")) 
    sourceToConvert.Save("c:\\tmp\\F1_gen.png", ImageFormat.Png);   

for (int i = 0; i < 100; i++) 
{ 
    using (Image sourceToConvert = Bitmap.FromFile("c:\\tmp\\F1.tif")) 
     sourceToConvert.Save("c:\\tmp\\F1_regen.png", ImageFormat.Png); 

    // files are the same 
} 

Zauważ, że znalazłem jedną dodatkową osobliwość: podczas uruchamiania 32-bitowy (x86) opiera się na Windows 7 SP1 x64, pierwszy dwa wywołania do Save zwróciły różne wyniki, następnie każde kolejne połączenie z numerem Save wytworzyło ten sam wynik co drugie połączenie. Aby przetestować test, musiałem powtórzyć pierwsze dwie linie (przed pętlą), aby wymusić dwa zapisy przed przeprowadzeniem kontroli równości.

+0

Dzięki za to! To trochę straszne, że finalizacja obrazu później powinna go zmodyfikować, ale twoje rozwiązanie działa idealnie na to, co chcę robić. Doskonały! – werner

Powiązane problemy