- PR -

ImageクラスのFileStreamで読み込んだ画像の保存

1
投稿者投稿内容
ひろ
会議室デビュー日: 2004/10/18
投稿数: 6
投稿日時: 2004-10-18 06:53
初めて投稿させていただきます。

画像処理用のアプリケーションを作成しています。
画像ファイルを読み込み、何かしらの処理を施し保存するといったものです。


処理を施した画像をImageクラスのSaveメソッドを用いて保存しようとしたところ、

'System.Runtime.InteropServices.ExternalException' のハンドルされていない例外が system.drawing.dll で発生しました。
追加情報 : GDI+ で一般的なエラーが発生しました。

と出ました。

色々調べてみると、画像を開く時に

Image sampleimage = Image.FromFile("sample.jpg");

と、ImageクラスのFromFileを使って画像ファイルを開くと、
そのアプリケーションを閉じるまではそのファイルにロックがかかるということで、
画像ファイルに変更を加えたりしようとすると、「共有違反がありました。」となるようです。
共有違反があって書き込みが出来ない時のエラー処理を怠っていたためだとわかりました。


マイクロソフト社のヘルプ
(http://support.microsoft.com/default.aspx?scid=kb;ja;311754)を参考にし、FileStreamオブジェクトを使うと解決できると書いてあったので、
その通りにしてみました。

FileStream fs;
fs = new FileStream("sample.jpg", FileMode.Open, FileAccess.Read);
Image sampleimage = System.Drawing.Image.FromStream(fs);
fs.Close();

これを

PictureBox.Image = sampleimage;

として割り当てれば画像は表示できました。
エクスプローラの方からファイルにアクセスし、
ファイル名などを変更しようとしても成功したので、
共有違反は回避できました。

ですが、Imageクラスに用意されているSaveメソッドで画像を保存しようとすると
エラーが起こるのです。コンパイラは通るのですが。

sampleimage.Save("another_sample.jpg",ImageFormat.jpeg);

上書きではなくても、エラーが起こるので、
共有違反といったわけではなさそうです。

何か考えられる原因について教えてもらえないでしょうか。
よろしくお願いします。
burton999
ぬし
会議室デビュー日: 2003/10/06
投稿数: 898
お住まい・勤務地: 東京
投稿日時: 2004-10-18 10:58
はずしているかもしれませんが
fs.Close();
でストリームを閉じてしまっているからではないでしょうか?
中博俊
ベテラン
会議室デビュー日: 2004/10/17
投稿数: 91
お住まい・勤務地: 大阪市
投稿日時: 2004-10-18 23:43
こんにちは中 博俊です。
フルパスにしてもだめでしょうか?
ひろ
会議室デビュー日: 2004/10/18
投稿数: 6
投稿日時: 2004-10-19 00:47
burton999様、中 博俊、ありがとうございます。

>フルパスにしてもだめでしょうか?

申し訳ないです。
実際のコードではここはフルパスを設定しています。


>はずしているかもしれませんが
>fs.Close();
>でストリームを閉じてしまっているからではないでしょうか?

なるほど。
今その可能性について色々テストしていますので、
結果をまた報告します。


ありがとうございました。
ひろ
会議室デビュー日: 2004/10/18
投稿数: 6
投稿日時: 2004-10-19 03:46
こんばんは、色々試してみました。

    引用:―――――――――――――――――――――――――
        はずしているかもしれませんが
        fs.Close();
        でストリームを閉じてしまっているからではないでしょうか?
      ――――――――――――――――――――――――――

Closeしない場合、
CloseするまでFileStreamで開いたファイルにロックがかかるようです。
なので、共有違反が起こるため、上書きなどはできませんでしたが、別名で保存などは可能でした。

一方、Closeした場合、
その前に、

Image testimage = Image.FromFile(openFileDialog1.FileName);
pictureBox1.Image = testimage;
pictureBox1.Image.Save("開いたファイル名とは違うファイル名",ImageFormat.jpeg)

と、FromFileを使った場合、pictureBox1には画像が表示され、
なおかつ保存することができます。
開いたファイル名と別名にしないと、ロックがかかっているために共有違反になります。

そこで、FromFileではなく、FileStreamを使ってみます。

FileStream fs;
fs = new FileStream(openFileDialog1.FileName, FileMode.Open, FileAccess.Read);
Image testimage = System.Drawing.Image.FromStream(fs);
fs.Close();
pictureBox1.Image = testimage;
pictureBox1.Image.Save("なんでも",ImageFormat.jpeg);

のようにして、pictureBox1のImageプロパティに割り当てると、
FromFileの時と同じ様にpictureBox1には画像が表示されます。
が、SaveのところでGDI+がエラーを起こします。


FileStreamを使った読み込みまでは載っているところも多いのですが、
Save時の問題については見つけることができませんでした。

どなたか、もし何か思い当たることなどがあれば、
是非ご教授願いたいです。
よろしくお願いします。
rvmx
大ベテラン
会議室デビュー日: 2002/09/26
投稿数: 184
お住まい・勤務地: 愛媛県
投稿日時: 2004-10-19 05:46
今日は

下記の様にすればうまくいくと思います。
ファイルより読み込む時は
pictureBox1.Image =new Bitmap(Image.FromFile(openFileDialog1.FileName));
ストリームより読み込む時
pictureBox1.Image =new Bitmap(fs);
ひろ
会議室デビュー日: 2004/10/18
投稿数: 6
投稿日時: 2004-10-19 22:50
rvmx様、どうもありがとうございます。

    引用:―――――――――――――――――――――――――

         ストリームより読み込む時
         pictureBox1.Image =new Bitmap(fs);

       ―――――――――――――――――――――――――

これを参考にしてやってみましたが、
やはりストリームをCloseすると、
pictureBox1.Image.Save(〜)メソッドでは保存できないようです。

ですが、Bitmapを使うのはちょっと思いつかなかったので、
色々試してみたところ、

FileStream fs;
fs = new FileStream(openFileDialog1.FileName, FileMode.Open, FileAccess.Read);
Bitmap bmp = (Bitmap)System.Drawing.Bitmap.FromStream(fs);
fs.Close();
pictureBox1.Image =new Bitmap(bmp);

とすれば、

pictureBox1.Image.Save(〜);

で、問題なく保存できました。


どうもありがとうございました。
1

スキルアップ/キャリアアップ(JOB@IT)