none
ビットマプを既存ファイルにセーブする RRS feed

  • 質問

  • 初めて投稿いたします。
    ビットマップをファイルから読み出し表示後内容を変更した後、Bitmap.Save でファイルにセーブする際に
    新しいファイル名を指定してセーブすれば正常に実行するのですが以前のファイルを指定すると
    ”同一ファイルが存在します、上書きしますか” を表示 "OK" を選択すると ”'GDI2' でエラーが発生しまいた” が
    スローされます
    初心者です、どこが悪いのでしょうか? ご教授お願いいたします

    使用言語は Visual Basic 2009 express
     コード
               If SaveFileDialog.ShowDialog() = Windows.Forms.DialogResult.OK Then
                    fname = SaveFileDialog.FileName

                    Try
                        MyBitMap_ORG.Save(fname)                    'bitmapを選択されたファイルにセーブする

                    Catch ex As Exception
                        MessageBox.Show(ex.Message, "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error)

                    End Try

                    MessageBox.Show("編集画面をビットマップに変換し、変換結果を" & fname & "にセーブしました")

                 End If

    2009年7月19日 6:21

回答

  • Bitmap.Saveメソッド はファイルを上書きすることはありません。必ずエラーになるので、事前に削除する必要があります。
    「同一ファイルが存在します、上書きしますか」と出しているのはSaveFileDialog の方です。
    これは「プログラムが上書きを行うかどうか」を確認するダイアログではなく、「ユーザーに上書きをする意志があるかどうか」を確認するダイアログです。
    実際の上書き処理は開発者に任されています。
    2009年7月19日 8:37
  • これは、ファイルがオープンされたままだろうと思い、オープンする Sub ないで削除しても同じエラーです
    どうすればいいのか、今一度教えてください
    お手数をかけて、申し訳ありません
    "MyBitMap_ORG"を作るときに、そのファイルから読み込むようにしていませんか?
    例えば、New Bitmap("c:\hogehoge.jpg")とか、Bitmap.FromFile("c:\hogehoge.jpg")として作ったインスタンスが生きている限り、"c:\hogehoge.jpg"は使用中になります。

    簡単に回避するには、一旦別の名前で保存してからリネームするとかでしょうか。

    前提:元のファイル名をAAA.jpg、一時的なファイル名をBBB.jpgとする。
    1.保存したいBitmapをBBB.jpgとしてSaveする。
    2.BitmapをDisposeする。
    3.AAA.jpgを削除する。
    4.BBB.jpgをAAA.jpgにリネームする。
    解決した場合は、参考になった返信に「回答としてマーク」のボタンを利用して、回答に設定しましょう(複数に設定できます)。
    2009年7月20日 7:56
    モデレータ
  • 多分、MyBitMap_ORG を PictureBox の Image プロパティあたりに設定しているのでは?
    (もしくは、Paint イベントで DrawImage の引数に使っているか)

    画面に表示しつつ、さらに上書きも行うということを両立したいのであれば、ファイルから読み込んだ後に、Bitmap のインスタンスのコピーを作る等の対応を行って、ファイルとの結びつきを取り除いて下さい。

    また、なぜ、それが必要かを十分にお考え下さい。


    解決した場合は、参考になった返信に「回答としてマーク」のボタンを利用して、回答に設定しましょう(複数に設定できます)。
    2009年7月22日 14:04
    モデレータ

すべての返信

  • Bitmap.Saveメソッド はファイルを上書きすることはありません。必ずエラーになるので、事前に削除する必要があります。
    「同一ファイルが存在します、上書きしますか」と出しているのはSaveFileDialog の方です。
    これは「プログラムが上書きを行うかどうか」を確認するダイアログではなく、「ユーザーに上書きをする意志があるかどうか」を確認するダイアログです。
    実際の上書き処理は開発者に任されています。
    2009年7月19日 8:37
  • 査祐理さん
    そうなんですか、わかりました
    どうもありがとうございました
    またよろしくご指導ください

    2009年7月19日 9:21
  • from hiro
    to     佐祐理さん

    bitmap.save は上書きはしない、事前に削除する必要がある、とのご指摘の通りSaveFileDialogをやめて
            'My.Computer.FileSystem.DeleteFile(FileName)    '以前のファイルを削除する
    で、削除を試みましたところ
    ”別のプロセスで使用されているため、プロセスはファイル "ファイル名" にアクセスできません” のエラーになりました
    これは、ファイルがオープンされたままだろうと思い、オープンする Sub ないで削除しても同じエラーです
    どうすればいいのか、今一度教えてください
    お手数をかけて、申し訳ありません

    2009年7月20日 1:26
  • これは、ファイルがオープンされたままだろうと思い、オープンする Sub ないで削除しても同じエラーです
    どうすればいいのか、今一度教えてください
    お手数をかけて、申し訳ありません
    "MyBitMap_ORG"を作るときに、そのファイルから読み込むようにしていませんか?
    例えば、New Bitmap("c:\hogehoge.jpg")とか、Bitmap.FromFile("c:\hogehoge.jpg")として作ったインスタンスが生きている限り、"c:\hogehoge.jpg"は使用中になります。

    簡単に回避するには、一旦別の名前で保存してからリネームするとかでしょうか。

    前提:元のファイル名をAAA.jpg、一時的なファイル名をBBB.jpgとする。
    1.保存したいBitmapをBBB.jpgとしてSaveする。
    2.BitmapをDisposeする。
    3.AAA.jpgを削除する。
    4.BBB.jpgをAAA.jpgにリネームする。
    解決した場合は、参考になった返信に「回答としてマーク」のボタンを利用して、回答に設定しましょう(複数に設定できます)。
    2009年7月20日 7:56
    モデレータ
  • "MyBitMap_ORG"を作るときに、そのファイルから読み込むようにしていませんか?
    例えば、New Bitmap("c:\hogehoge.jpg")とか、Bitmap.FromFile("c:\hogehoge.jpg")として作ったインスタンスが生きている限り、"c:\hogehoge.jpg"は使用中になります。

    簡単に回避するには、一旦別の名前で保存してからリネームするとかでしょうか。

    前提:元のファイル名をAAA.jpg、一時的なファイル名をBBB.jpgとする。
    1.保存したいBitmapをBBB.jpgとしてSaveする。
    2.BitmapをDisposeする。
    3.AAA.jpgを削除する。
    4.BBB.jpgをAAA.jpgにリネームする。
    Azuleanさん
    どうもありがとうございました、やってみます
    皆さんからいろいろ教えていただき感謝します
    2009年7月21日 2:55
  • fm hiro
    to  Azuleanさん

    ご指導ありがとうございます
           If Not (MyBitMap_ORG Is Nothing) Then
                 Try
                    MyBitMap_ORG.Save(NEW_fname)                            '別のファイル(tmp.bmp)にセーブする

                    MyBitMap_ORG.Dispose()                                      'MyBitMap_ORGを破棄する
                    MyBitMap_EDT = Nothing    '.Dispose()

                    My.Computer.FileSystem.DeleteFile(OLD_fname)         '元のファイルを削除する(あるとコピーでエラーになる)
                    My.Computer.FileSystem.CopyFile(NEW_fname, OLD_fname)   'セーブファイルを元のファイル名にコピーする
                    My.Computer.FileSystem.DeleteFile(NEW_fname)            'セーブファイルを削除する
                Catch ex As Exception
                    MessageBox.Show(ex.Message, "エラー、セーブせず終了!", MessageBoxButtons.OK, MessageBoxIcon.Error)
                    Return
                End Try

            Else
                MessageBox.Show("Bitmap画面のBitmapは構築されていません")
            End If
            MessageBox.Show("編集した画像を元のファイル名で保存を完了")
            Filewrite_Button.Enabled = False
        End Sub
    これでうまくセーブで来たのですが、End Sub の前のMessageboxも表示します
    その後ArgumentExceptionが発生し、"使用されたハンドルは有効でない" と表示されます
    普通例外が発生した時はどの命令で発生したか線で示されますがそれが表示されません、"ArgumentException はハンドルされなかった" で表示されます
    このSub以外の場所からきている気もしますがどこが悪いのでしょうか?
    お手数をおかけします、またよろしくお願いします

    2009年7月22日 4:44
  • 多分、MyBitMap_ORG を PictureBox の Image プロパティあたりに設定しているのでは?
    (もしくは、Paint イベントで DrawImage の引数に使っているか)

    画面に表示しつつ、さらに上書きも行うということを両立したいのであれば、ファイルから読み込んだ後に、Bitmap のインスタンスのコピーを作る等の対応を行って、ファイルとの結びつきを取り除いて下さい。

    また、なぜ、それが必要かを十分にお考え下さい。


    解決した場合は、参考になった返信に「回答としてマーク」のボタンを利用して、回答に設定しましょう(複数に設定できます)。
    2009年7月22日 14:04
    モデレータ
  • 多分、MyBitMap_ORG を PictureBox の Image プロパティあたりに設定しているのでは?
    (もしくは、Paint イベントで DrawImage の引数に使っているか)

    画面に表示しつつ、さらに上書きも行うということを両立したいのであれば、ファイルから読み込んだ後に、Bitmap のインスタンスのコピーを作る等の対応を行って、ファイルとの結びつきを取り除いて下さい。

    また、なぜ、それが必要かを十分にお考え下さい。

    from hiro
    to  Azuleanさん

      ご指導ありがとうございました
    指摘の通り、読み込んだビットマップを編集し上書きを実施するため

    1. bmp1に読み込みそのbmp1を7倍のbmp2に変換して
    2. マウス処理で編集しなおした結果をbmp1にの反映させ
    3. bmp1を上書き格納しています(前回のご指摘によりコピーで実施)
    4. bmp1、bmp2、PictureBox1,2 をDisporse
    5. コピーを元のファイル名にリネーム
    6. ここまで、PictureBox1,2用のPaintルーチンで再描画している(ファイルも意図どうりに格納)

    PaintルーチンでArgumentが空のスローがなされていることがわかりました
    Paintルーチンの先頭で
            If Not (BitMapPictureBox.Image Is Nothing) Then
           再描画処理
        End If
    しているのですがPaint1(元の画面用)ではスキップするのに Pain2(編集用画面用)ではスキップしません(編集用画面も表示のまま)
    どこかほかの所が悪いのだと思います
    もう少し考えてみます、何べんもご指導をいただき感謝いたします
    ありがとうございました

    2009年7月24日 1:46