2010-08-20 21 views
6

Sto tentando di ridimensionare e salvare un'immagine, che è abbastanza facile (per esempio, vedere questo esempio esempio esterno non è più valida).Ridimensiona e Salva Immagine preservando Metadati

Tuttavia, l'utilizzo di questo codice rimuove le informazioni sui metadati dall'immagine. Non riesco a capire come preservare i metadati per un'immagine jpeg.

** EDIT: Esempio di codice **

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]; 
} 

Grazie, WTS

+0

Il link indicato nel post non è più valido e conduce a siti discutibili. –

+0

@AlexJorgenson - rimosso il collegamento ormai vecchio di 7 anni - grazie. –

risposta

2

Utilizzare la proprietà Image.PropertyItems sull'immagine sorgente per ottenere l'elenco degli elementi di metadati. Passa attraverso l'elenco, chiamando Image.SetPropertyItem sull'immagine di destinazione. Normalmente dovresti evitare di ridimensionare e ricomprimere un'immagine jpeg, lavorando su un originale non compresso è meglio mantenere la qualità ed evitare artefatti.

+0

@ Hans - grazie per la risposta. Cordiali saluti - Il ridimensionamento è solo un modo per noi di aumentare l'efficienza in un'applicazione in cui la qualità non è un problema (anche se questo sarà testato) - stiamo preservando anche i file originali. –

+0

Un'immagine jpeg ridimensionata per renderla più piccola e salvata spesso richiede * più * spazio. –

+0

Forse se usi targetImage.SetPropertyItem() invece di targetFile. Mi aspetto di diagnosticare il tuo problema da questo non è realistico. –