图片框上的C#GDI + ScaleTransform可以,但保存的图像是原始的 [英] C# GDI+ ScaleTransform ok on picturebox but image saved is original

查看:475
本文介绍了图片框上的C#GDI + ScaleTransform可以,但保存的图像是原始的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个问题,当我使用ScaleTransform(zoomFactor,zoomFactor)时,保存在磁盘上的图像始终是原始版本,而在图片框的屏幕上,图像会按照zoomFactor的比例失真. 为什么会发生这种情况?我不应该将e.Graphics的最终结果应用于磁盘写入的图像吗?

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:\tmp\photoid\" + 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将其在屏幕上显示的内容绘制为 new 位图,然后可以保存该位图!

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.

某处表示其他某处,不在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!

相反,请执行以下操作:

Instead do something like this:

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.

但是,如果要直接缩放,为什么不使用需要 2 RectanglesDrawImage重载?这是最常见的解决方案,如果您想缩放所有内容并可能另外绘制其他内容..

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.与其他解决方案一样,除非将其重新分配回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 ;

别忘了处置旧图像.

这篇关于图片框上的C#GDI + ScaleTransform可以,但保存的图像是原始的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆