C# GDI+ ScaleTransform 在 picturebox 上正常,但保存的图像是原始图像
C# GDI+ ScaleTransform ok on picturebox but image saved is original
您好,我有一个问题,当我使用 ScaleTransform(zoomFactor,zoomFactor) 时,保存在磁盘上的图像始终是原始版本,而在屏幕上的 picturebox 中,图像与 zoomFactor 成比例地扭曲。
为什么会这样?我不应该在磁盘写入映像上应用 e.Graphics 的最终结果吗?
我的代码如下,是矩阵版本。但是我也使用了 ScaleTransform 而不是矩阵。结果总是一样的:
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:\tmp\photoid\" + new Random(seed).Next() + "_conv.jpg";
//Here I get always the original image back!!!!
bmp.Save(destinationFile);
我也使用了以下成语,但结果相同:
//Matrix matrix = new Matrix();
//matrix.Scale(zoomFac, zoomFac);
//e.Graphics.Transform = matrix;
自从我弄乱 GDI 以来已经有一段时间了,但我认为您需要在此处复制回位图。
g.DrawImage(bmp, scaledwidth, scaledheight);
在bmp.Save
之前尝试类似的东西
编辑
很抱歉没有看到您正在复制回位图。也许指定输出矩形的重载就是您所需要的。尝试具有目标 Rect 的 DrawImage 重载。 https://msdn.microsoft.com/en-us/library/ms142040(v=vs.110).aspx
您需要让 PictureBox
将它在屏幕上显示的内容绘制成 新 位图,然后您可以保存它!
因为它是 Image
将以原始形式保存,而你在 Paint
事件中所做的任何事情,实际上绘制到 PictureBox
的表面都将被保存.
所以要保存所有内容,即 Image
,可能是 BackgroundImage
以及您在 Paint
事件中绘制的所有内容,您会调用 DrawToBitmap
somehwere。
Somewhere 表示某处 else,不在 Paint
事件中,因为它将调用 Paint
事件创建新的 Bitmap
,导致无限循环..
要调用它,您需要这样做:
Bitmap bmpSave = new Bitmap(pictureBox1.ClientSize.Width, pictureBox1.ClientSize.Height);
pictureBox1.DrawToBitmap(bmpSave, pictureBox1.ClientRectangle);
但这也许不是你真正想要的?也许你真的想修改Image
?在这种情况下,不要 使用 Paint
事件!
而是做这样的事情:
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(...);
}
您可以从触发缩放的地方调用它。
请注意,每次从以前的缩放版本重复缩放会相当快地降低质量。为此,请始终从原始版本的保存版本进行缩放!!
顺便说一句:使用 Matrix
进行缩放并没有真正对 ScaleTransform
产生影响。
但是如果你想直接缩放为什么不使用需要 two Rectangles
的 DrawImage
重载?这是最常见的解决方案,如果你想要缩放并可能另外绘制其他东西..:[=36=]
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
..:[=36=]
pictureBox1.Image = bmp ;
不要忘记处理旧图像..
您好,我有一个问题,当我使用 ScaleTransform(zoomFactor,zoomFactor) 时,保存在磁盘上的图像始终是原始版本,而在屏幕上的 picturebox 中,图像与 zoomFactor 成比例地扭曲。 为什么会这样?我不应该在磁盘写入映像上应用 e.Graphics 的最终结果吗?
我的代码如下,是矩阵版本。但是我也使用了 ScaleTransform 而不是矩阵。结果总是一样的:
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:\tmp\photoid\" + new Random(seed).Next() + "_conv.jpg";
//Here I get always the original image back!!!!
bmp.Save(destinationFile);
我也使用了以下成语,但结果相同:
//Matrix matrix = new Matrix();
//matrix.Scale(zoomFac, zoomFac);
//e.Graphics.Transform = matrix;
自从我弄乱 GDI 以来已经有一段时间了,但我认为您需要在此处复制回位图。
g.DrawImage(bmp, scaledwidth, scaledheight);
在bmp.Save
之前尝试类似的东西编辑 很抱歉没有看到您正在复制回位图。也许指定输出矩形的重载就是您所需要的。尝试具有目标 Rect 的 DrawImage 重载。 https://msdn.microsoft.com/en-us/library/ms142040(v=vs.110).aspx
您需要让 PictureBox
将它在屏幕上显示的内容绘制成 新 位图,然后您可以保存它!
因为它是 Image
将以原始形式保存,而你在 Paint
事件中所做的任何事情,实际上绘制到 PictureBox
的表面都将被保存.
所以要保存所有内容,即 Image
,可能是 BackgroundImage
以及您在 Paint
事件中绘制的所有内容,您会调用 DrawToBitmap
somehwere。
Somewhere 表示某处 else,不在 Paint
事件中,因为它将调用 Paint
事件创建新的 Bitmap
,导致无限循环..
要调用它,您需要这样做:
Bitmap bmpSave = new Bitmap(pictureBox1.ClientSize.Width, pictureBox1.ClientSize.Height);
pictureBox1.DrawToBitmap(bmpSave, pictureBox1.ClientRectangle);
但这也许不是你真正想要的?也许你真的想修改Image
?在这种情况下,不要 使用 Paint
事件!
而是做这样的事情:
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(...);
}
您可以从触发缩放的地方调用它。
请注意,每次从以前的缩放版本重复缩放会相当快地降低质量。为此,请始终从原始版本的保存版本进行缩放!!
顺便说一句:使用 Matrix
进行缩放并没有真正对 ScaleTransform
产生影响。
但是如果你想直接缩放为什么不使用需要 two Rectangles
的 DrawImage
重载?这是最常见的解决方案,如果你想要缩放并可能另外绘制其他东西..:[=36=]
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
..:[=36=]
pictureBox1.Image = bmp ;
不要忘记处理旧图像..