代码之家  ›  专栏  ›  技术社区  ›  Wonko the Sane

在保留元数据的同时调整和保存图像的大小

  •  7
  • Wonko the Sane  · 技术社区  · 14 年前

    我正在尝试调整和保存图像,这相当容易(例如, 请参阅此示例 外部示例不再有效 )

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

    1 回复  |  直到 7 年前
        1
  •  2
  •   Hans Passant    14 年前

    使用源映像上的image.property items属性获取元数据项列表。在列表中循环,调用目标映像上的image.setPropertyItem。通常情况下,您应该避免调整大小和重新压缩JPEG图像,从未压缩的原始图像进行操作是保持质量和避免伪影的最佳方法。