2009-07-27 14 views
6

Próbuję obsługiwać obracanie obrazów JPEG z ASP.NET MVC (z przyrostem 90 stopni). Próbuję użyć System.Drawing (GDI +), jednak mam problemy.Obracanie plików JPEG w .NET przy minimalnej utracie jakości

Próbowałem użyć Image.RotateFlip, która jest w stanie obrócić obraz, ale powoduje utratę jakości. Nawet przy jakości enkodera wynoszącej 100, nadal widoczne są artefakty na obróconym obrazie, które nie były na oryginalnym obrazie, ani nie pojawiają się, gdy obracam je za pomocą innych programów (Gimp, itp.).

using (Image image = Image.FromFile("C:\\source.jpg")) { 
    ImageFormat sourceFormat = image.RawFormat; 
    image.RotateFlip(RotateFlipType.Rotate90FlipNone); 
    EncoderParameters encoderParams = null; 
    try { 
     if (sourceFormat == ImageFormat.Jpeg) { 
      encoderParams = new EncoderParameters(1); 
      encoderParams.Param[0] = new EncoderParameter(Encoder.Quality, 100L); 
     } 
     image.Save("C:\\target.jpg", GetEncoder(sourceFormat), encoderParams); 
    } finally { 
     if (encoderParams != null) 
      encoderParams.Dispose(); 
    } 
} 

Znalazłem artykuł na temat transforming a JPEG without loss of information. Korzystanie Encoder.Transformation wydaje się być opcja z .NET - jednak nie mogę zmusić go do powodują żadnej z moich obrazów testowych JPEG obracać w ogóle, czy wymiary są wielokrotnością 16.

using (Image image = Image.FromFile("C:\\source.jpg")) { 
    ImageFormat sourceFormat = image.RawFormat; 
    EncoderParameters encoderParams = null; 
    try { 
     if (sourceFormat == ImageFormat.Jpeg) { 
      encoderParams = new EncoderParameters(1); 
      encoderParams.Param[0] = new EncoderParameter(Encoder.Transformation, 
       (long)EncoderValue.TransformRotate90); 
     } 
     image.Save("C:\\target.jpg", GetEncoder(sourceFormat), encoderParams); 
    } finally { 
     if (encoderParams != null) 
      encoderParams.Dispose(); 
    } 
} 

Czy ktoś wie jak z powodzeniem obracać JPEG w .NET w krokach co 90 stopni przy minimalnej lub zerowej utracie jakości przy użyciu jednej z powyższych metod lub innej metody? Dzięki.

Również tutaj moja realizacja GetEncoder:

private ImageCodecInfo GetEncoder(ImageFormat format) { 
    foreach (var info in ImageCodecInfo.GetImageEncoders()) 
     if (info.FormatID == format.Guid) 
      return info; 
    return null; 
} 

Edit:

zaktualizowałem powyższy kod w celu lepszego dopasowania mój rzeczywisty kod. Błąd był w następującej linii:

if (sourceFormat == ImageFormat.Jpeg) { 

Powinno być:

if (sourceFormat.Guid == ImageFormat.Jpeg.Guid) { 
+2

Twój kod działa dla mnie .. czy jesteś pewien, że ImageCodecInfo jest zwracana dla twoich danych? –

+0

Dzięki @ pb, otrzymałem ImageCodecInfo, ale nie encoderParams, ponieważ mój rzeczywisty kod miał dodatkowy czek przed ustawieniem, który miał błąd. –

Odpowiedz

1

Dzięki za potwierdzenie, że moja pisał kod zadziałał. To pomogło mi wyizolować mój problem. Teraz czuję się głupio. Moje rzeczywisty kod miał czek na format obrazu przed ustawieniem encoderParams - ale miał błąd:

if (sourceFormat == ImageFormat.Jpeg) { 
    // set encoderParams here 

odkryłem powyżej warunkowa była zawsze fałszywe tak encoderParams nie był ustawiony. Poprawka była prosta:

if (sourceFormat.Guid == ImageFormat.Jpeg.Guid) { 
2

Za pomocą dowolnej metody, która rozpakowuje obraz, obraca go i kompresuje, utracisz jakość.

Format JPEG kompresuje informacje o kolorach w kwadratach o wielkości 2x2 pikseli, uzyskując średni kolor reprezentujący wszystkie cztery piksele, więc jeśli szerokość i wysokość obrazu są podzielne przez dwa, utracisz niższą jakość, ponieważ większość informacji usuniętych z kompresja to informacja interpolowana podczas dekompresji.

Podobnie informacje o jasności są kompresowane w kwadraty o wymiarach 8x8 pikseli, więc jeśli szerokość i wysokość są podzielne przez osiem, siatka wyrówna się po obróceniu obrazu, a utracisz mniej informacji rzeczywistych.

Aby wykonać obrót bezstratny, należy użyć zupełnie innej metody, odczytując plik JPEG i zmieniając kolejność poszczególnych pól informacji tak, aby tworzył obrócony obraz bez jego dekompresji i ponownego kompresowania.

Powiązane problemy