2010-08-20 2 views
6

Je tente de redimensionner et enregistrer une image, ce qui est assez facile (par exemple, voir cet exemple exemple externe plus valide). Toutefois, l'utilisation de ce code supprime les informations de métadonnées de l'image. Je n'arrive pas à comprendre comment préserver les métadonnées d'une image jpeg.Redimensionner et enregistrer l'image tout en préservant les métadonnées

** EDIT: Exemple de code **

public static void ResizeMethodThree(string sourceFile, string targetFile) 
    { 
     byte[] baSource = File.ReadAllBytes(sourceFile); 

     PropertyItem[] propertyItems = new Bitmap(sourceFile).PropertyItems; 

     using (Stream streamPhoto = new MemoryStream(baSource)) 
     { 
      BitmapFrame bfPhoto = ReadBitmapFrame(streamPhoto); 
      BitmapMetadata metaData = (BitmapMetadata)bfPhoto.Metadata; 
      int nNewPictureSize = 200; 
      int nWidth = 0; 
      int nHeight = 0; 

      if (bfPhoto.Width > bfPhoto.Height) 
      { 
       nWidth = nNewPictureSize; 
       nHeight = (int)(bfPhoto.Height * nNewPictureSize/bfPhoto.Width); 
      } 
      else 
      { 
       nHeight = nNewPictureSize; 
       nWidth = (int)(bfPhoto.Width * nNewPictureSize/bfPhoto.Height); 
      }   

      BitmapFrame bfResize = ResizeHelper(bfPhoto, nWidth, nHeight, BitmapScalingMode.HighQuality); 

      byte[] baResize = ToByteArray(bfResize); 

      File.WriteAllBytes(targetFile, baResize); 

      Image targetImage = new Bitmap(targetFile); 
      foreach (var propertyItem in propertyItems) 
      { 
       targetImage.SetPropertyItem(propertyItem); 
      } 

      targetImage.Save(targetFile); 
     } 
    } 

    public static BitmapFrame ResizeHelper(BitmapFrame photo, int width, 
              int height, BitmapScalingMode scalingMode) 
    { 

     var group = new DrawingGroup(); 
     RenderOptions.SetBitmapScalingMode(
      group, scalingMode); 
     group.Children.Add(
      new ImageDrawing(photo, 
       new Rect(0, 0, width, height))); 
     var targetVisual = new DrawingVisual(); 
     var targetContext = targetVisual.RenderOpen(); 
     targetContext.DrawDrawing(group); 
     var target = new RenderTargetBitmap(
      width, height, 96, 96, PixelFormats.Default); 
     targetContext.Close(); 
     target.Render(targetVisual); 
     var targetFrame = BitmapFrame.Create(target); 
     return targetFrame; 
    } 

private static byte[] ToByteArray(BitmapFrame bfResize) 
{ 
    using (MemoryStream msStream = new MemoryStream()) 
    { 
     JpegBitmapEncoder jpgEncoder = new JpegBitmapEncoder(); 
     jpgEncoder.Frames.Add(bfResize); 
     jpgEncoder.Save(msStream); 
     return msStream.ToArray(); 
    } 
} 

private static BitmapFrame ReadBitmapFrame(Stream streamPhoto) 
{ 
    BitmapDecoder bdDecoder = 
     BitmapDecoder.Create(streamPhoto, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.None); 
    return bdDecoder.Frames[0]; 
} 

Merci, WTS

+0

Le lien référencé dans le message n'est plus valide et conduit à des sites douteux. –

+0

@AlexJorgenson - enlevé le lien maintenant âgé de 7 ans - merci. –

Répondre

2

Utilisez la propriété Image.PropertyItems sur l'image source pour obtenir la liste des éléments de métadonnées. Parcourez la liste en appelant Image.SetPropertyItem sur l'image de destination. Vous devriez normalement éviter de redimensionner et de recompresser une image jpeg, travailler à partir d'un original non compressé est préférable de maintenir la qualité et éviter les artefacts.

+0

@Hans - merci pour la réponse. FYI - Le redimensionnement est juste un moyen pour nous d'augmenter l'efficacité dans une application où la qualité n'est pas un problème (bien que cela sera testé) - nous préservons également les fichiers originaux. –

+0

Une image jpeg redimensionnée pour la réduire et la sauvegarder nécessite souvent * plus * d'espace. –

+0

Peut-être que vous utilisez targetImage.SetPropertyItem() au lieu de targetFile. S'attendre à ce que je diagnostique votre problème n'est pas réaliste. –

Questions connexes