Question

I am attempting to resize and save an image, which is fairly easy (for instance, see this example external example no longer valid).

However, using this code strips the metadata information from the image. I can't quite seem to figure out how to preserve the metadata for a jpeg image.

**EDIT: Example 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];
}

Thanks, wTs

Was it helpful?

Solution

Use the Image.PropertyItems property on the source image to get the list of metadata items. Loop through the list, calling Image.SetPropertyItem on the destination image. You should normally avoid resizing and re-compressing a jpeg image, working from an uncompressed original is best to maintain quality and avoid artifacts.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top