开发者

Expand canvas/transparent background in BitmapImage in a WPF app

This is a follow up question on Save image to file keeping aspect ration in a WPF app

I know howto scale the image, but how do I expand the canvas size, to ensure the image still has the requested width and height. In this example its 250x250 but its dynamic.

I have created this illustration to show what I'm trying to accomplice.

Expand canvas/transparent background in BitmapImage in a WPF app

I can't find any way开发者_Go百科 of expanding the canvas of an BitmapImage, nor a way to create an in memory image in the correct size, with a transparent background, and then merging the two images together.


CroppedBitmap doesn't seem to support adding space around an image so instead you can create a transparent image the correct size using WriteableBitmap. If the input is smaller than the target size this method will enlarge it, but that is easy to alter.

public static BitmapSource FitImage(BitmapSource input, int width, int height)
{
    if (input.PixelWidth == width && input.PixelHeight == height)
        return input;

    if(input.Format != PixelFormats.Bgra32 || input.Format != PixelFormats.Pbgra32)
        input = new FormatConvertedBitmap(input, PixelFormats.Bgra32, null, 0);

    //Use the same scale for x and y to keep aspect ratio.
    double scale = Math.Min((double)width / input.PixelWidth, height / (double)input.PixelHeight);

    int x = (int)Math.Round((width - (input.PixelWidth * scale))/2);
    int y = (int)Math.Round((height - (input.PixelHeight * scale))/2);


    var scaled = new TransformedBitmap(input, new ScaleTransform(scale, scale));
    var stride = scaled.PixelWidth * (scaled.Format.BitsPerPixel / 8);

    var result = new WriteableBitmap(width, height, input.DpiX, input.DpiY, input.Format,null);

    var data = new byte[scaled.PixelHeight * stride];
    scaled.CopyPixels(data, stride, 0);
    result.WritePixels(new Int32Rect(0,0,scaled.PixelWidth,scaled.PixelHeight), data, stride,x,y);
    return result;
}

If you are already rendering content using RenderTargetBitmap you could wrap it in a ViewBox to do the scaling but if you're just working with normal images I'd use the above method.


You should be able to set the Stretch property to Uniform.


Just some code in case others are trying to postprocess files from a form upload.

if (file.PostedFile != null)
{
    //write the new file to disk
    string cachePath = String.Format("{0}temp\\", Request.PhysicalApplicationPath);
    string photoPath = String.Format("{0}temp.png", cachePath);                
    if (!Directory.Exists(cachePath))
{
   Directory.CreateDirectory(cachePath);
}    

file.PostedFile.SaveAs(photoPath);

//resize the new file and save it to disk               
BitmapSource banana = FitImage(ReadBitmapFrame(file.PostedFile.InputStream), 640, 480);
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(banana));
FileStream pngStream = new FileStream(cachePath + "test.png", FileMode.Create);
encoder.Save(pngStream);
pngStream.Close();

//set a couple images on page to the newly uploaded and newly processed files
image.Src = "temp/temp.png";
image.Visible = true;
image2.Src = "temp/test.png"; 


   image2.Visible = true;
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜