C# GDI+ ScaleTransform 在图片框上正常,但保存的图像是原始图像
我遇到的问题是,当我使用 ScaleTransform(zoomFactor,zoomFactor) 时,保存在磁盘上的图像始终是原始版本,而在图片框的屏幕上,图像会与 zoomFactor 成比例地失真.为什么会发生这种情况?我不应该得到从 e.Graphics on disk write image 应用的最终结果吗?
Hi I have the issue that when I use ScaleTransform(zoomFactor,zoomFactor) the image saved on disk is the original version always, while on screen in the picturebox the image is distorted in proportion to the zoomFactor. Why this could be happening ? Shouldn't I have the final result as applied from e.Graphics on disk written image ?
我的代码如下,这是一个带有矩阵的版本.但是我也使用了 ScaleTransform 而不是矩阵.结果总是一样的:
My code is the following which is a version with matrix. but the instead of matrix I have used the ScaleTransform as well. Result is always the same:
g=e.Graphics;//inside picturebox_paint()
g.ScaleTransform(ratio * zoomFac, ratio * zoomFac);
e.Graphics.DrawImage((Bitmap)bmp, 0, 0);
int seed = Convert.ToInt32(Regex.Match(Guid.NewGuid().ToString(), @"d+").Value);
String destinationFile = @"C: mpphotoid" + new Random(seed).Next() + "_conv.jpg";
//Here I get always the original image back!!!!
bmp.Save(destinationFile);
我也使用了以下习语,但结果相同:
I have used as well the following idiom but with same results:
//Matrix matrix = new Matrix();
//matrix.Scale(zoomFac, zoomFac);
//e.Graphics.Transform = matrix;
你需要让 PictureBox
把它在屏幕上显示的东西绘制成一个 新的 Bitmap,它然后你就可以保存了!
You need to make the PictureBox
draw the things it shows on screen into a new Bitmap, which you then can save!
实际上,Image
将以原始形式保存,而您在 Paint
事件中没有做任何事情,它实际上是绘制在 PictureBox 的表面上
将被保存.
As it is the Image
will be saved in the original form and nothing you did in the Paint
event, which actually painst onto the surface of the PictureBox
will be saved.
所以要保存所有内容,即 Image
,可能是 BackgroundImage
以及您在 Paint
事件中绘制的所有内容,您将调用 DrawToBitmap
某处.
So to save everything, i.e. The Image
, possibly a BackgroundImage
and all you draw in the Paint
event you would call DrawToBitmap
somehwere.
Somewhere 表示某处else,不在 Paint
事件中,因为它会调用 Paint
事件来创建新的Bitmap
,导致无限循环..
Somewhere means somewhere else, not in the Paint
event, as it will call the Paint
event to create the new Bitmap
, causing an endless loop..
要调用它,您将执行以下操作:
To call it you would do something like this:
Bitmap bmpSave = new Bitmap(pictureBox1.ClientSize.Width, pictureBox1.ClientSize.Height);
pictureBox1.DrawToBitmap(bmpSave, pictureBox1.ClientRectangle);
但这也许不是您真正想要的?也许你真的想修改Image
?在这种情况下,根本不要使用 Paint
事件!
But maybe this is not really what you want? Maybe you actually want to modify the Image
? In that case do not use the Paint
event at all!
改为这样做:
Bitmap bmpSave = new Bitmap(yourNewWidth, yourNewHeight);
using (Graphics g = Graphics.FromImage(bmpSave))
{
g.ScaleTransform(ratio * zoomFac, ratio * zoomFac);
g.DrawImage((Bitmap)pictureBox1.Image, 0, 0); //
pictureBox1.Image = bmpSave;
bmpSave.Save(...);
}
您可以从触发缩放的地方调用它.
You could call this from somewhere where the scaling is being triggered from.
请注意,从以前的缩放版本重复进行缩放,每次都会降低质量.为此,始终从原始版本的保存版本进行缩放!!
Note that doing the scaling repeatedly and each time from the previoulsy scaled version will degrade the quality rather fast. For this always scale from a saved version of the original!!
顺便说一句:使用 Matrix
进行缩放与 ScaleTransform
相比并没有真正的区别.
Btw: Using a Matrix
for scaling doesn't really make a difference over ScaleTransform
.
但如果你想直接缩放,为什么不使用 DrawImage
重载,它需要 两个 矩形
?如果您想要缩放并可能另外绘制其他东西,这是最常见的解决方案..:
But if you want to do a direct scaling why not use the DrawImage
overload which takes two Rectangles
? This is the most common solution if all you want to to scale and maybe draw other stuff additionally..:
int newWidth = 100; int newHeight = 100; string yourFileName = "D:\xyz123.jpg";
Bitmap bmpSave = new Bitmap(pictureBox1.ClientSize.Width, pictureBox1.ClientSize.Height);
Rectangle newRectangle = new Rectangle(0, 0, newWidth, newHeight);
Rectangle oldRectangle = new Rectangle(Point.Empty, pictureBox1.Image.Size);
using (Graphics g = Graphics.FromImage(bmpSave))
{
g.DrawImage((Bitmap)pictureBox1.Image, newRectangle, oldRectangle, GraphicsUnit.Pixel);
bmpSave.Save(yourFileName, ImageFormat.Jpeg);
}
还有缩放Bitmap
构造函数:
Bitmap bmp = new Bitmap(pictureBox1.Image, newWidth, newHeight);
如果您只想缩放 Image
,我会推荐它.与其他解决方案一样,它不会更改显示的 Image
,直到您将其分配回 PictureBox
..:
Which I would recommend if all you want is to scale the Image
. As the other solutions it will not change the Image
displayed until you assign it back into the PictureBox
..:
pictureBox1.Image = bmp ;
不要忘记处理旧图像..
Don't forget to dispose of the old Image..