2

Stack Overflow 全体を検索しましたが、次の回答が見つかりませんでした。

OpenFileDialogを使用している場合、開いたファイルは、プログラムを閉じるまで、プログラムから使用できないようにブロックされます。そのため、画像を開いた場合、 Windows エクスプローラーでその画像を置き換えることはできなくなりました。

これは OpenFileDialog を破棄する際の問題だと思いますが、解決方法がわかりません...

私のコード:

using (OpenFileDialog ofd = new OpenFileDialog())
{
    ofd.Title = "Open Image";
    ofd.Filter = "PNG Image(*.png|*.png" +
                 "|GIF Image(*.gif|*.gif" +
                 "|Bitmap Image(*.bmp|*.bmp" +
                 "|JPEG Compressed Image (*.jpg|*.jpg";

    if (ofd.ShowDialog() == DialogResult.OK)
    {
        pictureBox1.Image = new Bitmap(ofd.FileName);
    }
}

ブロックがこの問題を解決してくれると思っていたのusingですが、違います...それでもプログラムによって使用されます。画像をピクチャボックスにロードしたいので、画像を再び利用できるようにしたいです(名前を変更したり、置き換えたりすることができます...)。

4

3 に答える 3

5

これは、OpenFileDialog とは関係ありません。ダイアログは実際にはファイルを開かないため、そうである可能性はありません。ユーザーが開くファイルを選択できるようにし、そのパスを返すだけで、ファイルを開くコードを記述できるようになります。さらに、ステートメントを使用して OpenFileDialog を正しく破棄していますusing

ここでの問題は、実際にファイル (<code>ofd.FileName) をビットマップとして開いていることにあります。パス文字列を受け入れる Bitmap コンストラクター オーバーロードを使用すると、イメージを含むディスク上のファイルは、Bitmap オブジェクトが破棄されるまでロックされたままになります。ドキュメントには次のように書かれています。

ビットマップが破棄されるまで、ファイルはロックされたままになります。

ビットマップを に割り当てているためpictureBox1.Image、Bitmap オブジェクトは が破棄されるまで破棄されませんpictureBox1。したがって、ディスク上の画像ファイルはロックされたままになります。

ファイルのロックを解除する場合は、ビットマップのコピーを作成して元のイメージを破棄するか、PictureBox をクリアして、作業が終了したときに前のイメージを破棄する必要があります。

あなたの質問を理解しているように、画像ボックスに画像を表示し続けながら、ディスク上の画像ファイルを変更できるようにしたいようです。その場合は、コピーを作成する必要があります。次のように、イメージを受け取るコンストラクターのオーバーロードを使用してそれを行います。

if (ofd.ShowDialog() == DialogResult.OK)
{
    // Load the image the user selected
    using (Image img = Image.FromFile(ofd.FileName))
    {
        // Create a copy of it
        Bitmap bmpCopy = new Bitmap(img);

        // Clear out the bitmap currently in the picture box,
        // if there is one.
        if (pictureBox1.Image != null)
        {
            pictureBox1.Image.Dispose();
        }

        // Assign the copy of the bitmap to the picture box.
        pictureBox1.Image = bmpCopy;
    }
}
于 2013-08-11T13:02:02.343 に答える
1

Chris が書いたように、次のようにしてみてください。

pictureBox1.Image = Image.FromStream(new MemoryStream(File.ReadAllBytes(old.FileName)));

ですべてのファイルを読み取りFile.ReadAllBytes、 a に入れ、静的初期化子にMemoryStream渡します。MemoryStreamImage

に相当:

byte[] bytes = File.ReadAllBytes(old.FileName);
MemoryStream ms = new MemoryStream(bytes);
pictureBox1.Image = Image.FromStream(ms);

MemoryStream!を破棄してはなりません。が破棄される場合/いつ、ImageのファイナライザーがMemoryStream起動し ( への他の参照がない場合ms)、MemoryStreamが破棄されます (これはすぐに発生するものではないことに注意してください...それは発生するものですGC がいつ実行されるか)

于 2013-08-11T13:09:35.960 に答える
0

私が見つけた最良の手法は、File.ReadAllBytes() (ファイルを開いたり閉じたりする) を使用してファイルをバイト配列に読み取り、次に ImageConverter を使用してバイト配列を画像に変換することです。たとえば、こちらを参照してください: https://stackoverflow.com/a/16576471/253938

編集: 私の以前の投稿からの引用: 「私が試した他の手法のいくつかは、ピクセルのビット深度 (24 ビット対 32 ビット) を変更したり、画像の解像度を無視したりしたため、最適ではありませんでした ( dpi)」

于 2013-08-11T13:22:20.013 に答える