简体   繁体   中英

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. 替代文字

I can't find any way 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.

您应该能够将Stretch属性设置为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;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM