1

最初に、タイル画像を表示するためのドラッグアンドドロップ機能を備えたデスクトップAIRアプリを作成しましたが、いくつかの問題のため、C#で同じものを作成しようとしました。何がより良い選択だと思いますか?(私はこの小さなプログラムのパフォーマンスが問題ではないことを知っていますが、私は両方の難しさと複雑さを意味します)

単純なTileViewerを作成していたので、画像がopenFileDialogで選択され、フォームのタイル化されたBackgroundImageとして設定されます。

私の問題は:

  1. タイマー(間隔= 500)を使用して画像をリロードしているので、フォトショップで画像を編集すると、TileViewerは更新された画像を自動的にリロードします(フォトショップに保存すると)。

    しかし、問題は、フォトショップにそうするための権限がないことです。画像は他のプログラム(私のTileViewer)で開かれます。

  2. タイマーを外して、代わりに更新ボタンを作成しました。しかし、それは同じ問題です。

ビットマップデータのコピーを作成しようと思いましたが、32px x32pximgに十分なメモリがないというエラーが表示されます。

私のコード:

    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 );
    }

ですから、何か提案や解決策があれば、私に知らせてください。

4

3 に答える 3

2

Bitmap.Clone()メソッドは、期待どおりの動作をしません。「浅い」コピーを作成します。新しいビットマップオブジェクトを取得しますが、それでも基になるピクセルバッファを使用します。GDI+がピクセルデータをスワップファイルに入れないようにするために使用するメモリマップトファイルを含みます。これにより、ファイルがロックされます。

「ディープ」コピーを作成する必要があります。これは、Bitmap(Image)コンストラクターを使用して行います。このような:

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

usingステートメントは、元のイメージが破棄され、ロックが解放されることを保証します。

于 2012-09-11T18:21:39.717 に答える
2

更新 2:

もう 1 つの問題は、インライン Rectangle rect = new Rectangle(0, 0, 100, 100); でした。

コンストラクターでは、100 のような任意の値ではなく、新しい画像の幅と高さを渡す必要があります。

それが、ランタイムがメモリ不足だと言っている理由です!! (それは私のために行いました.18 GBのモンスターマシンを持っています)

アップデート:

オブジェクトがリークしているため、メモリ不足の例外が発生します

(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() {
Bitmap tempImg = new Bitmap( ファイル名 ); <--- Rectangle rect = new Rectangle(0, 0, 100, 100);
PixelFormat フォーマット = tempImg.PixelFormat;

    this.BackgroundImage = new Bitmap( FileName ).Clone( rect, format );  
}  
于 2012-09-11T18:17:48.767 に答える
0

ReadOnly フラグを使用してファイルを手動で開き、ファイルのペイロードを手動でビットマップにロードする必要があります。

別の方法は、ファイルをコピーしてからコピーを開くことです。

Photoshop でファイルを開いている間に次のコードを実行できるかどうかを確認してください

 FileStream s2 = new FileStream(name, FileMode.Open, FileAccess.Read, FileShare.Read);
于 2012-09-11T18:04:26.043 に答える