2016-01-12 23 views
5

Mój program przetwarza niektóre obrazy w serii. W tej chwili muszę odczytać znacznik orientacji exif obrazu, obrócić go do właściwej orientacji, zrobić niektóre przetwarzanie i zapisać obraz bez EXIF ​​Orientation tag, ale z właściwego obrotu (lub z EXIF ​​tag z właściwej orientacji)Pobierz znacznik orientacji EXIF, obróć do właściwej orientacji, wyświetl obraz procesu i zapisz go z odpowiednią orientacją.

czytam EXIF ​​i obracanie za pomocą this library.

var bmp = new Bitmap(pathToImageFile); 
    var exif = new EXIFextractor(ref bmp, "n"); // get source from http://www.codeproject.com/KB/graphics/exifextractor.aspx?fid=207371 

    if (exif["Orientation"] != null) 
    { 
    RotateFlipType flip = OrientationToFlipType(exif["Orientation"].ToString()); 

    if (flip != RotateFlipType.RotateNoneFlipNone) // don't flip of orientation is correct 
    { 
    bmp.RotateFlip(flip); 
    bmp.Save(pathToImageFile, ImageFormat.Jpeg); 
    } 

    // Match the orientation code to the correct rotation: 

    private static RotateFlipType OrientationToFlipType(string orientation) 
    { 
    switch (int.Parse(orientation)) 
    { 
    case 1: 
    return RotateFlipType.RotateNoneFlipNone; 

    case 2: 
    return RotateFlipType.RotateNoneFlipX; 

    case 3: 
    return RotateFlipType.Rotate180FlipNone; 
    case 4: 
    return RotateFlipType.Rotate180FlipX; 
    break; 
    case 5: 
    return RotateFlipType.Rotate90FlipX; 
    break; 
    case 6: 
    return RotateFlipType.Rotate90FlipNone; 
    case 7: 
    return RotateFlipType.Rotate270FlipX; 
    case 8: 
    return RotateFlipType.Rotate270FlipNone; 
    default: 
    return 
} 
} 

To działa. ale przy zapisywaniu tego obrazu nadal istnieje znacznik obrotu Exif, który sprawia, że ​​obraz ma niewłaściwą orientację. Co mogę zrobić, to

 var bmp = new Bitmap(OS.FileName);  
     var exif = new EXIFextractor(ref bmp, "n"); 
     exif.setTag(0x112, "1"); 
     bmp.save("strippedexifimage"); 

Ale ten kod stosowany w pętli spowalnia mojego programu o około 50% .Is istnieje alternatywny sposób? Może to być kod do obrócenia obrazu po obróceniu, czy to zadziała?

Aktualizacja:

@Hans passant swoje prace odpowiedź, ale wynik jest produkować takie same jak te wytwarzane przez bibliotekę. Kiedy używam bitmap.save(), zarówno biblioteka, jak i twój kod działają. Ale kiedy używam następującego kodu, aby zapisać obraz w zależności od formatu wybranego przez użytkownika. Imgformat może być imgformat = "image/png";,imgformat = "image/jpeg"; itp. Niektóre zdjęcia są nadal zapisywane z niewłaściwym znacznikiem orientacji exif. tj: widzę niewłaściwy podgląd obrazu w Eksploratorze Windows, Kiedy otwieram obraz z MS Paint, obraz ma prawidłową orientację.Co im robię źle? Proszę pomóż.

private void saveJpeg(string path, Bitmap img, long quality) 
     { 


      EncoderParameter qualityParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, quality); 


      ImageCodecInfo Codec = this.getEncoderInfo(imgformat); 
      if (Codec == null) 
       return; 

      EncoderParameters encoderParams = new EncoderParameters(1); 
      encoderParams.Param[0] = qualityParam;  
      img.Save(path + ext, Codec, encoderParams); 
     } 



private ImageCodecInfo getEncoderInfo(string mimeType) 
     { 
      // Get image codecs for all image formats 
      ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders(); 

      // Find the correct image codec 
      for (int i = 0; i < codecs.Length; i++) 
       if (codecs[i].MimeType == mimeType) 
        return codecs[i]; 
      return null; 
     } 
+0

Spójrz na ImageMagick. Myślę, że robi wszystko, co chcesz. Możesz napisać kod dla niego .. lub po prostu użyć go tak jak jest. :) – atlaste

Odpowiedz

5
var exif = new EXIFextractor(ref bmp, "n") 

Korzystanie z biblioteki do realizacji funkcji można zaoszczędzić dużo czasu. Lub utkniesz przez kilka dni, gdy biblioteka jest źle zaprojektowana lub trudna w użyciu. ref bmp jest pierwszym głośnym alarmem, który wpadł w rozpacz, próbując określić wartość jako ciąg znaków. Co było atrakcyjne, ponieważ nie trzeba było zastanawiać się, co "typ" może oznaczać w poprawnym przeciążeniu setTag(). Jest to typ 3 i wymaga bajtu [] z dwoma elementami. Nie można tego w ogóle wykryć, możesz korzystać z biblioteki tylko wtedy, gdy jej nie potrzebujesz.

Porzuć bibliotekę, to nie jest pomocne. Tag EXIF ​​przechowujący orientację ma identyfikator 0x112 i jest zakodowany jako 16-bitowa wartość. Wystarczy użyć System.Drawing bezpośrednio, aby odczytać wartość i zmusić ją z powrotem do 1. W ten sposób:

static void FixImageOrientation(Image srce) { 
    const int ExifOrientationId = 0x112; 
    // Read orientation tag 
    if (!srce.PropertyIdList.Contains(ExifOrientationId)) return; 
    var prop = srce.GetPropertyItem(ExifOrientationId); 
    var orient = BitConverter.ToInt16(prop.Value, 0); 
    // Force value to 1 
    prop.Value = BitConverter.GetBytes((short)1); 
    srce.SetPropertyItem(prop); 

    // Rotate/flip image according to <orient> 
    switch (orient) { 
     // etc... 
    } 
} 
+0

Bardzo dziękuję. Przeszukałem, czy był sposób, aby zrobić to bezpośrednio za pomocą kodu, ale nie mogłem znaleźć żadnych. "Orient" zwracanych wartości, które są w moim przypadku przełącznika (mam na myśli 1,2,3. .etc) – techno

+0

Proszę zobaczyć aktualizację. – techno

+0

Czy możesz podzielić się swoją opinią na temat mojej aktualizacji sir? – techno