在WPF中调整图像大小

7

我有一张图片,想要调整尺寸并保存在我的临时文件夹中。

我尝试的方法如下:

UIElement uie = CanvasHost.Child;
int width = 800;
int height = (int)((width / (double)((FrameworkElement)uie).Width) * (int)((FrameworkElement)uie).Height);          
RenderTargetBitmap rtb = new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Pbgra32);
rtb.Render(uie);

string dir = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + @"\temp\";
if (!Directory.Exists(dir))
      Directory.CreateDirectory(dir);

long size = 0;

string filePath = dir + DateTime.Now.Ticks.ToString() + (isPng ? ".png" : ".jpg");
BitmapEncoder enc = null;

using (FileStream fs = File.Create(filePath))
{
    if (isPng)
        enc = new PngBitmapEncoder();
    else
        enc = new JpegBitmapEncoder();

    enc.Frames.Add(BitmapFrame.Create(rtb));
    enc.Save(fs);

    size = fs.Length;
}

但是当我创建像这样的图像时,它会将图像的一部分保存在临时文件夹中(如上图所示)。如何调整完整图像的大小?我错过了什么?编辑:正如Erti-Chris Eelmaa在上面的答案中提到的那样,我已将代码更改如下。现在它可以工作......
UIElement uie = CanvasHost.Child;
int width = DataCache.Instance.CurrentProject.MaxPhotoEdgeSize;
int height = (int)((width / (double)((FrameworkElement)uie).Width) * (int)((FrameworkElement)uie).Height);

RenderTargetBitmap rtb = new RenderTargetBitmap((int)((FrameworkElement)uie).Width, (int)((FrameworkElement)uie).Height, 96, 96, PixelFormats.Pbgra32);
rtb.Render(uie);

ImageSource im = (ImageSource)rtb.Clone();
BitmapFrame bp = CreateResizedImage(im, width, height, 1); //method suggested by Erti-Chris Eelmaa
string dir = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + @"\temp\";

if (!Directory.Exists(dir))
    Directory.CreateDirectory(dir);

long size = 0;

string filePath = dir + DateTime.Now.Ticks.ToString() + (isPng ? ".png" : ".jpg");
BitmapEncoder enc = null;

using (FileStream fs = File.Create(filePath))
{
    if (isPng)
         enc = new PngBitmapEncoder();
    else
         enc = new JpegBitmapEncoder();


    enc.Frames.Add(BitmapFrame.Create(bp));
    enc.Save(fs);

    size = fs.Length;
}

创建位图后,您需要更改其高度和宽度。您现在所做的是创建一个小尺寸的新位图,并将其填充为原始图片而不进行调整大小。您应该创建一个与原始尺寸相同的位图,然后使用其高度和宽度来更改其大小。 - fhnaseer
@FaisalHafeez,你能再详细解释一下吗?我该如何重新调整它的大小? - DevT
在这里,您正在制作一个宽度和高度大小的位图。现在这是缩小后的尺寸。但当您将其填充为图像时,它只会复制图像的一部分(在您的情况下发生了这种情况)。您需要使用其他函数来实现这一点。 - fhnaseer
@FaisalHafeez,你能建议我在这里做什么吗? - DevT
尝试使用 Erti 提供的解决方案,看起来很好。 - fhnaseer
2个回答

32

关于大小调整本身,使用WPF的TransformedBitmap似乎更容易些:

var bitmap = new TransformedBitmap(bitmapSource, 
    new ScaleTransform(
        newWidth / bitmapSource.PixelWidth, 
        newHeight / bitmapSource.PixelHeight));

我会说 - 容易多了 :) - Wolfrevok Cats
简洁明了!谢谢! - undefined

22

使用这种方法获取BitmapFrame,之后你可以使用PngBitmapEncoder将其保存到硬盘上。

private static BitmapFrame CreateResizedImage(ImageSource source, int width, int height, int margin)
{
    var rect = new Rect(margin, margin, width - margin * 2, height - margin * 2);

    var group = new DrawingGroup();
    RenderOptions.SetBitmapScalingMode(group, BitmapScalingMode.HighQuality);
    group.Children.Add(new ImageDrawing(source, rect));

    var drawingVisual = new DrawingVisual();
    using (var drawingContext = drawingVisual.RenderOpen())
        drawingContext.DrawDrawing(group);

    var resizedImage = new RenderTargetBitmap(
        width, height,         // Resized dimensions
        96, 96,                // Default DPI values
        PixelFormats.Default); // Default pixel format
    resizedImage.Render(drawingVisual);

    return BitmapFrame.Create(resizedImage);
}

我已经使用了这个函数,你的意思是说要用PngBitmapEncoder代替RenderTargetBitmap,对吗?如果是这样,那么我该如何保存enc.Frames.Add(BitmapFrame.Create(rtb));呢?因为在这里需要一个可视对象。 - DevT
我编辑了我的问题。当我这样保存时,它保存了一张黑色的图片。为什么会这样? - DevT
1
即使这是一个相当古老的答案,它仍然像魔法一样有效!谢谢你救了我的一天! - Error 404 Brain not found
太棒了!你肯定不会相信处理图像有多么困难。 - Rafael Ventura

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接