Bitmap image = ReadBitmap("image.png");
Bitmap imageCopy = new Bitmap(image);
Bitmap canvas = new Bitmap(imageCopy.Width+100, imageCopy.Height);
// From this bitmap, the graphics can be obtained, because it has the right PixelFormat
using(Graphics g = Graphics.FromImage(canvas))
{
// Draw the original bitmap onto the graphics of the new bitmap
g.DrawImage(image, 0, 0);
}
// Use tempBitmap as you would have used originalBmp
InputPictureBox.Image = image;
OutputPictureBox.Image = canvas;
我不了解此C#代码的输出。
原始图像未放置在正确的位置。应该是(0,0)。
我还需要黑色背景。
那么,怎么回事以及如何纠正呢?
答案 0 :(得分:3)
您正在加载图像,然后使用以下方法创建此源的副本:
Bitmap bitmap = new Bitmap();
以这种方式创建图像副本时,您会牺牲/更改一些细节:
Dpi Resolution :如果未另行指定,则将分辨率设置为UI分辨率。标准为96 Dpi;不同的屏幕分辨率和缩放比例可能会有所不同。使用中的系统也会影响此值(Windows 7和Windows 10可能/可能会提供不同的值)
PixelFormat :如果未直接从图像源复制或未明确指定,则PixelFormat
将设置为PixelFormat.Format32bppArgb
。
根据您的发言,您可能想要这样的东西:
using (Bitmap imageSource = (Bitmap)Image.FromFile(@"[SomeImageOfLena]"))
using (Bitmap imageCopy = new Bitmap(imageSource.Width + 100, imageSource.Height, imageSource.PixelFormat))
{
imageCopy.SetResolution(imageSource.HorizontalResolution, imageSource.VerticalResolution);
using (Graphics g = Graphics.FromImage(imageCopy))
{
g.Clear(Color.Black);
g.CompositingMode = CompositingMode.SourceCopy;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.DrawImage(imageSource, (imageCopy.Width - imageSource.Width) / 2, 0);
pictureBox1.Image = (Image)imageSource.Clone();
pictureBox2.Image = (Image)imageCopy.Clone();
}
}
这是结果:
(上/下边框黑色实际上是Picturebox
背景色)
当原始图像Dpi分辨率与使用new Bitmap()
创建图像副本时使用的基本Dpi分辨率不同时,您的结果可能与预期的不同。
在相同的情况下,源图像为150、96和72 Dpi时会发生以下情况:
另一个重要的细节是Image对象的IDisposable性质。
创建一个时,您必须Dispose()个它;显式地调用Dispose
方法,或隐式地将Image构造器包含在Using statement中。
也可能不分配直接从Image
加载的FileStream
对象。
GDI +将锁定文件,您将无法复制,移动或删除它。
使用该文件,与图像相关的所有资源也将被锁定。
使用new Bitmap()
(如果您不关心上述细节)或使用Image.Clone()进行复制,这将保留图像Dpi Resolution
和PixelFormat
。
答案 1 :(得分:0)
我不清楚您实际上需要做什么。但是无论如何,这是一个WPF友好示例,说明了如何在另一张图像内的特定位置绘制图像。
请注意,如果您要做的只是显示不同大小的图像和/或在其周围放置黑色边框,则有许多更简单的方法可以简单地做到这一点,而不必创建第二个图像,例如只是布局面板中的图像已经具有所需的边框样式。
请注意,我正在使用System.Windows.Media命名空间中的类,因为这是WPF使用的。这些不容易与System.Drawing命名空间中的旧类混合使用(某些类名称冲突,并且Microsoft的.Net框架缺少用于在这些类型之间转换对象的内置方法),因此通常需要简单地决定是否使用一组绘图工具。我认为您一直在尝试使用System.Drawing。每个人都有自己的优缺点,在这里要花太长时间来解释。
// using System.Windows.Media;
// using System.Windows.Media.Imaging;
private void DrawTwoImages()
{
// For InputPictureBox
var file = new Uri("C:\\image.png");
var inputImage = new BitmapImage(file);
// If your image is stored in a Resource Dictionary, instead use:
// var inputImage = (BitmapImage) Resources["image.png"];
InputPicture.Source = inputImage;
// imageCopy isn't actually needed for this example.
// But since you had it in yours, here is how it's done, anyway.
var imageCopy = inputImage.Clone();
// Parameters for setting up our output picture
int leftMargin = 50;
int topMargin = 5;
int rightMargin = 50;
int bottomMargin = 5;
int width = inputImage.PixelWidth + leftMargin + rightMargin;
int height = inputImage.PixelHeight + topMargin + bottomMargin;
var backgroundColor = Brushes.Black;
var borderColor = (Pen) null;
// Use a DrawingVisual and DrawingContext for drawing
DrawingVisual dv = new DrawingVisual();
using (DrawingContext dc = dv.RenderOpen())
{
// Draw the black background
dc.DrawRectangle(backgroundColor, borderColor, new Rect(0, 0, width, height));
// Copy input image onto output image at desired position
dc.DrawImage(inputImage, new Rect(leftMargin, topMargin,
inputImage.PixelWidth, inputImage.PixelHeight));
}
// For displaying output image
var rtb = new RenderTargetBitmap( width, height, 96, 96, PixelFormats.Pbgra32 );
rtb.Render(dv);
OutputPicture.Source = rtb;
}