降低C#

时间:2017-10-16 20:53:51

标签: c# memory graphics gdi drawimage

我将图像存储在位图中。当我调整对象大小时,我的图像也需要调整大小。我已经做了一个功能,将我的图像调整到所需的大小。

当我绝对需要调整图像大小时,我已经只调用了这个函数,但是我不断地将这个图像大小的内存成本从50 MB迅速跳到1 GB以上。 (当按住鼠标按钮时,需要在每毫秒调用此方法。)

我在Graphics中拥有using但在这种情况下似乎没什么帮助。 如果我在其上调用GC.Collect(2)当然有帮助,但它会极大地降低GUI的速度,如果我将其设置为非阻塞,那么它根本不会有任何帮助。

有没有办法释放被调用的此函数的最后一个实例仍未使用的内存,或者我是否需要更改我的代码并以另一种方式执行此操作?如果有更好的方式我会欣赏一些帮助,因为似乎GDI漏洞或我的方法效率很低。

我的代码:

public int getWidth()
{
    return width;
}

public int getHeight()
{
    return height;
}

public void createScaledImage()
{
    var cr = new c_returnGraphicSettings();
    if (getWidth() > 20 && getHeight() > 20)
    {
        scaledImage = new Bitmap(getWidth(), getHeight());
        using (Graphics g = Graphics.FromImage(scaledImage))
        {
            /*
            g.InterpolationMode = cr.getIM();
            g.PixelOffsetMode = cr.getPOM();
            g.SmoothingMode = cr.getSM();
            /*--*/

            g.DrawImage(image, new Rectangle(new Point(0, 0), scaledImage.Size), new Rectangle(new Point(0, 0), image.Size), GraphicsUnit.Pixel);
            g.Dispose();
        }

        //GC.Collect(2, GCCollectionMode.Forced, true);

    }
}

public Bitmap getScaledImage()
{
    //createScaledImage();
    return scaledImage;
}

public void resizeImage()
{
    if(image != null)
    {
        createScaledImage();
    }
}

主要表格的代码:

protected override void OnPaint(PaintEventArgs e)
{
    base.OnPaint(e);

    //TODO: PAINT!!
    organizeImageList();
    foreach (c_ImageHolder c in Limages)
    {
        if (c != null)
        {
            e.Graphics.DrawImage(c.getScaledImage(), c.Position);
            ...
        }
    }
}


private void f_Screen_MouseDown(object sender, MouseEventArgs e)
{
    Limages.Sort(new intComparerDesc());
    foreach (c_ImageHolder c in Limages)
    {
        if (renhan.pointInPosition(e.Location, new Rectangle(c.Position, c.Size)))
        {
            c.select();
            selectedImage = c;
            imageDragPoint = new Point(e.X - c.Left, e.Y - c.Top);
            if (!c.isOverAnEdge(imageDragPoint) && !c.isOverACorner(imageDragPoint)) 
            { 
                resize = false; 
                cResizer = null; 
                ed = edges.none; 
                cor = corners.none; 
            }
            else 
            { 
                resize = true; 
                cResizer = c; 
                if (c.isOverAnEdge(imageDragPoint))
                { 
                    ed = c.overWhichEdge(imageDragPoint); 
                    cor = corners.none; 
                } 
                else 
                { 
                    cor = c.overWhichCorner(imageDragPoint); 
                    ed = edges.none; 
                } 
            }
            mdown = true;
            break;
        }
    }
    Invalidate();
}

enter image description here

说明:

我使用我制作的类来存储位图图像及其大小和位置的一些数据,然后我用它将该图像绘制到存储此类实例的屏幕上。

由于透明度问题,我没有使用控件(图片框等)。

每个实例包含不同的图像。我还需要能够调整这些图像的大小。出于这个原因,我有第二个位图,我存储原始位图的调整版本。

我使用不同的位图来存储已调整大小的图像,这样如果我需要再次调整大小,我就不会调整已经修改的图像的大小,而是调整原始图像的大小。 (保持质量)

调整大小如下: 我按住图像边缘上的鼠标按钮。当我每次调整大小时按住按钮的同时移动鼠标时,类会生成一个新图像,将原始图像拉伸到新尺寸上。将该图像返回到无效的主屏幕,并在绘制时将新图像绘制到屏幕背景上。

问题在于,由于我需要将此图像绘制到背景上,因此我无法处理它。我可以复印并处理原件,但我认为,那时候我也有同样的问题。

当我按住鼠标按钮并不断重新绘制图像时,内存会迅速增加。我完成后可以处理,但只要调整图像大小就可以使程序崩溃。

我制作了一个更简单,更简单的程序来演示我的问题以及您可以在这里找到的简短视频:Video and link to program

我的演示程序链接存储在Dropbox的视频下的rar文件中。

我希望这个解释和视频/演示有助于更好地解释我的问题。

感谢所有想要帮助的人!

1 个答案:

答案 0 :(得分:0)

感谢所有试图提供帮助的人。我finalyl意识到我哪里出错了。

当我在控件中管理图像时,我保留了原始代码的功能。

使用我的新代码,我可以管理调整大小而无需将其写入新的位图。

我不知道为什么我不明白,就像5个人告诉我同样的事情。

再次感谢。