2010-08-20 62 views
6

我试图调整大小并保存图像,这很容易(例如, 请参阅此示例 外部示例不再有效)。保存元数据时调整大小和保存图像

但是,使用此代码将从图像中去除元数据信息。我似乎无法弄清楚如何保存JPEG图像的元数据。

**编辑:示例代码**

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

感谢, WTS

+0

帖子中引用的链接不再有效并导致可疑网站。 – 2017-10-23 15:17:56

+0

@AlexJorgenson - 删除了现在7岁的链接 - 谢谢。 – 2017-10-23 19:05:22

回答

2

使用源图像上的Image.PropertyItems属性来获取元数据项的列表。循环访问列表,在目标图像上调用Image.SetPropertyItem。您通常应该避免调整大小并重新压缩jpeg图像,从未压缩的原始图像处理最好能够保持质量并避免失真。

+0

@Hans - 谢谢你的回答。仅供参考 - 调整大小只是提高质量不成问题的应用程序效率的一种方式(尽管这将进行测试) - 我们也保留原始文件。 – 2010-08-20 15:57:18

+0

这是一个JPEG格式的图像,调整大小使其更小,并保存回往往需要*更多*空间。 – 2010-08-20 16:04:18

+0

也许如果你使用targetImage.SetPropertyItem()而不是targetFile。期待我从这个问题诊断你的问题是不现实的。 – 2010-08-20 17:58:14

相关问题