【问题标题】:Resize and Save Image While Preserving Metadata在保留元数据的同时调整图像大小和保存图像
【发布时间】:2011-04-01 16:54:28
【问题描述】:

我正在尝试调整图像大小并保存,这很容易(例如,查看此示例外部示例不再有效)。

但是,使用此代码会从图像中去除元数据信息。我似乎不太明白如何保存 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];
}

【问题讨论】:

  • 帖子中引用的链接不再有效,并导致有问题的网站。
  • @AlexJorgenson - 删除了已有 7 年历史的链接 - 谢谢。

标签: c# wpf image-processing metadata image-resizing


【解决方案1】:

使用源图像的 Image.PropertyItems 属性来获取元数据项的列表。循环遍历列表,在目标图像上调用 Image.SetPropertyItem。您通常应避免调整大小和重新压缩 jpeg 图像,最好使用未压缩的原始图像来保持质量并避免伪影。

【讨论】:

  • @Hans - 谢谢你的回答。仅供参考 - 调整大小只是我们在质量不是问题的应用程序中提高效率的一种方式(尽管这将被测试) - 我们也在保留原始文件。
  • 调整大小以使其更小并保存回来的 jpeg 图像通常会占用 更多 空间。
  • 如果你使用 targetImage.SetPropertyItem() 而不是 targetFile。期望我由此诊断您的问题是不现实的。
  • 之前的评论因类型而被删除。我正在编辑我的问题以显示我正在尝试的内容。
  • 这是 WPF 和 GDI+ 代码的丑陋组合。它不起作用,因为您将图像重新保存为 PNG 格式。您必须通过 ImageFormat。
猜你喜欢
  • 1970-01-01
  • 2010-10-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-20
  • 1970-01-01
  • 1970-01-01
  • 2021-08-26
相关资源
最近更新 更多