C#-在其他程序中编辑背景图像时实时更新背景图像



首先,我制作了一个带有拖放功能的桌面AIR应用程序来查看瓷砖图像,但由于一些问题,我尝试在C#中制作同样的应用程序。你认为什么是更好的选择?(我知道这个小程序的性能不是问题,但我指的是两者的愚蠢和复杂性)

我正在构建一个简单的TileViewer,所以在openFileDialog中选择一张图片,并将其设置为Form的平铺BackgroundImage。

我的问题是:

  1. 我一直在使用计时器(间隔=500)来重新加载图像,所以如果我在photoshop中编辑图像,TileViewer将自动重新加载更新的图像(就像我在photohop中保存它一样)。

    但问题是,photoshop没有这样做的前提,因为图像是在另一个程序(我的TileViewer)中打开的

  2. 我去掉了定时器,改为刷新按钮。但问题是一样的。

我想复制位图数据,但后来我得到一个错误,我没有足够的内存用于32px x 32px img。

我的代码:

    private string FileName;
    public Form1() {
        InitializeComponent();
        FileName = "";
    }
    // OPEN FILE btn
    private void button1_Click( object sender, EventArgs e ) {
        openFileDialog1.Filter = "PNG Files (*.png)|*.png|JPG Files (*.jpg)|*.jpg";
        if(openFileDialog1.ShowDialog() == DialogResult.OK) {
            button2.Enabled = true;
            FileName = openFileDialog1.FileName;
            setImage();
        }
    }
    // REFRESH btn
    private void button2_Click( object sender, EventArgs e ) {
        if( FileName != "" ) {
            setImage();
        }
    }
    private void setImage() {
        Bitmap tempImg = new Bitmap( FileName );
        Rectangle rect = new Rectangle(0, 0, 100, 100);
        PixelFormat format = tempImg.PixelFormat;
        this.BackgroundImage = new Bitmap( FileName ).Clone( rect, format );
    }

所以,伙计们,如果你们有任何建议或解决方案,请告诉我。

更新2:

另一个问题是矩形矩形rect=新矩形(0,0,100,100);

在构造函数中,应该传递新图像的宽度和高度,而不是像100这样的任意值。

这就是为什么运行时会说你内存不足!!(它为我做了,我有一台18GB的怪物机器)

更新:

您正在泄漏对象,因此出现内存不足异常

(Haans已经警告过你要处理那些东西了。)

尝试以下代码

private string FileName;
public Form1()
{
    InitializeComponent();
    FileName = "";
}
// OPEN FILE btn 
private void button1_Click(object sender, EventArgs e)
{
    openFileDialog1.Filter = "PNG Files (*.png)|*.png|JPG Files (*.jpg)|*.jpg";
    if (openFileDialog1.ShowDialog() == DialogResult.OK)
    {
        FileName = openFileDialog1.FileName;
        setImage();
    }
}
// REFRESH btn 
private void button2_Click(object sender, EventArgs e)
{
    if (FileName != "")
    {
        setImage();
    }
}
private void setImage()
{
Stream str=new FileStream(FileName,FileMode.Open, FileAccess.Read,FileShare.Read);
        Bitmap tempImg= new Bitmap(Bitmap.FromStream(str));
        str.Close();
        using( tempImg)
        {

        Rectangle rect = new Rectangle(0, 0, tempImg.Width, tempImg.Height);
        PixelFormat format = tempImg.PixelFormat;
        this.BackgroundImage = new Bitmap(tempImg);
        }
}

旧答案

就像杰森说的

你可能需要在你的setimage方法中做一些类似的事情

Stream str = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read);
   this.BackgroundImage  = Bitmap.FromStream(str);
str.Close();

注意,你最好关闭你使用后打开的任何流。

而不是

private void setImage(){
位图tempImg=新位图(FileName)&lt---矩形rect=新矩形(0,0,100,100)
PixelFormat format=tempImg.PixelFormat;

    this.BackgroundImage = new Bitmap( FileName ).Clone( rect, format );  
}  

Bitmap.Clone()方法并不能实现您所希望的效果。它创建了一个"浅"副本。您得到了一个新的位图对象,但它仍然使用底层像素缓冲区。包括GDI+用来将像素数据排除在交换文件之外的内存映射文件。这反过来又锁定了文件。

您需要制作一个"深度"副本,使用位图(图像)构造函数即可。像这样:

private void setImage() {
    using (var tempImg = new Bitmap(FileName)) {
        this.BackgroundImage = new Bitmap(tempImg);
    }
}

using语句确保释放原始图像并释放锁。

您需要使用ReadOnly标志手动打开文件,然后手动将文件的有效负载加载到位图中。

一种替代方法是复制文件,然后打开副本。

看看你是否可以在photoshop打开文件时运行以下代码

 FileStream s2 = new FileStream(name, FileMode.Open, FileAccess.Read, FileShare.Read);

最新更新