C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[5]: マルチtiff内の画像の保存でGDI+汎用エラー


(過去ログ 133 を表示中)

[トピック内 6 記事 (1 - 6 表示)]  << 0 >>

■78571 / inTopicNo.1)  マルチtiff内の画像の保存でGDI+汎用エラー
  
□投稿者/ ゲート (1回)-(2016/01/26(Tue) 15:43:59)

分類:[VB.NET/VB2005 以降] 

使用言語:VB2008
OS:Windows7

マルチtiff画像を分解してgifファイルに変換しようと試みています。
色々と調べた結果、以下の方法でtiffファイルの各ページを分解してBitmap形式のデータを
取り込むことはできたのですが、これを保存(Save)する際に
「GDI+ で汎用エラーが発生しました」という例外が発生します。

    Private Sub SaveImages(ByVal tifFile As String)
        'tifFileはTiffファイルのフルパス

        Using fs As New FileStream(tifFile, FileMode.Open, FileAccess.Read, FileShare.Read)
            Dim bmd As BitmapDecoder = BitmapDecoder.Create(fs, _
                                                            BitmapCreateOptions.PreservePixelFormat, _
                                                            BitmapCacheOption.Default)
            For intIdx As Integer = 0 To bmd.Frames.Count - 1
                Dim bmf As BitmapFrame = bmd.Frames(intIdx)
                Dim savePath As String = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), _
                                                      "img_" & intIdx.ToString & ".gif")
                Using bmp As Bitmap = ConvertBitmapFrameToBitmap(bmf)
                    bmp.Save(savePath, Imaging.ImageFormat.Gif)    '←ここで例外発生
                End Using
            Next
        End Using

        MsgBox("終了")
    End Sub

    Private Function ConvertBitmapFrameToBitmap(ByVal bmf As BitmapFrame) As Bitmap
        Dim enc As New BmpBitmapEncoder()
        enc.Frames.Add(bmf)

        Using ms As New MemoryStream
            enc.Save(ms)
            Return Bitmap.FromStream(ms)
        End Using
    End Function

なお、ファイル保存用の変数savePathは適切(含まれているフォルダは存在する)であることを確認しております。
(例えば別のgifファイルをこの名前で保存できることを確認しました。)

また、

    Using bmp As Bitmap 〜

の部分を

    Dim bmp As Bitmap 〜

に変更し、この内容をPictureBoxのImageプロパティに設定すると、問題なく画像が表示されます。
ただし、このBitmap変数に対してSaveを行おうとすると、同様の例外が出ます。

この例外の原因として考えられることは何でしょうか?
よろしくお願いします。

引用返信 編集キー/
■78572 / inTopicNo.2)  Re[1]: マルチtiff内の画像の保存でGDI+汎用エラー
□投稿者/ Hongliang (402回)-(2016/01/26(Tue) 15:59:17)
2016/01/26(Tue) 16:00:06 編集(投稿者)

StreamからBitmapオブジェクトを作成した場合、Bitmapを破棄するまでは元のStreamをDisposeしてはいけません。
またBitmapのDisposeでStreamも自動的にDisposeされます。
// ちなみに、MemoryStreamは特にDisposeする必要もないです。

ところで、デコードにWIC(System.Windows.Media.Imaging)を使用するなら、エンコードにもWICを使えば良いのではないでしょうか?
GifBitmapEncoderを使えばいちいちBitmapオブジェクト経由したりも不要で直接BitmapFrameで扱えますが。

逆に、どうせGDI+(System.Drawing)を使うなら、デコードからBitmapを使えば良いのでは。
こっちの場合、マルチフレームは、
・Image::FrameDimensionsListからFrameDimensionを作り、
・GetFrameCountでフレーム数を取得し、
・SelectActiveFrameでアクティブフレームを切り替え、
・そのままSaveすればアクティブなフレームが保存されます。
引用返信 編集キー/
■78573 / inTopicNo.3)  Re[2]: マルチtiff内の画像の保存でGDI+汎用エラー
□投稿者/ ゲート (2回)-(2016/01/26(Tue) 16:50:37)
Hongliang 様、アドバイスありがとうございます。
元々はTiffの各画像をBitmapとして取得するようなサンプルを参考にしたため、
GifBitmapEncoderというものを知りませんでした。

早速、GifBitmapEncoderを調べて、以下のようにしたら
うまくGifファイルの保存ができました。
ありがとうございました。助かりました。

    Private Sub SaveImages(ByVal tifFile As String)
        'tifFileはTiffファイルのフルパス

        Using fs As New FileStream(tifFile, FileMode.Open, FileAccess.Read, FileShare.Read)
            Dim bmd As BitmapDecoder = BitmapDecoder.Create(fs, _
                                                            BitmapCreateOptions.PreservePixelFormat, _
                                                            BitmapCacheOption.Default)
            For intIdx As Integer = 0 To bmd.Frames.Count - 1
                Dim bmf As BitmapFrame = bmd.Frames(intIdx)
                Dim savePath As String = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), _
                                                      "img_" & intIdx.ToString & ".gif")
                Dim enc As New GifBitmapEncoder()
                enc.Frames.Add(bmf)
                Using fss As New FileStream(savePath, FileMode.Create)
                    enc.Save(fss)
                End Using
            Next
        End Using

        MsgBox("終了")
    End Sub


ところで、今回の問題は、GifBitmapEncoderを使うことで解決しましたが、
お恥ずかしながら、イマイチよく理解できていない点があります。

> StreamからBitmapオブジェクトを作成した場合、Bitmapを破棄するまでは元のStreamをDisposeしてはいけません。

の部分が、最初の質問時に提示したコードのどの部分を指しているのかが分かりませんでした。
もしよろしければ、ご教示頂けると幸いです。

引用返信 編集キー/
■78574 / inTopicNo.4)  Re[3]: マルチtiff内の画像の保存でGDI+汎用エラー
□投稿者/ Hongliang (403回)-(2016/01/26(Tue) 16:54:48)
>>StreamからBitmapオブジェクトを作成した場合、Bitmapを破棄するまでは元のStreamをDisposeしてはいけません。
> 
> の部分が、最初の質問時に提示したコードのどの部分を指しているのかが分かりませんでした。
> もしよろしければ、ご教示頂けると幸いです。

ここですね。
>> Using ms As New MemoryStream
>>     enc.Save(ms)
>>     Return Bitmap.FromStream(ms)
>> End Using
Bitmapの作成元となるmsが、Usingによって自動的にDisposeされてしまっています。

引用返信 編集キー/
■78578 / inTopicNo.5)  Re[4]: マルチtiff内の画像の保存でGDI+汎用エラー
□投稿者/ ゲート (3回)-(2016/01/27(Wed) 10:08:50)
Hongliang 様、回答ありがとうございます。
ようやく理解できました。

> ここですね。
> >> Using ms As New MemoryStream
> >> enc.Save(ms)
> >> Return Bitmap.FromStream(ms)
> >> End Using
> Bitmapの作成元となるmsが、Usingによって自動的にDisposeされてしまっています。

MemoryStreamもStreamですね。お恥ずかしい限りです。。。

この場合は、

> またBitmapのDisposeでStreamも自動的にDisposeされます。
> // ちなみに、MemoryStreamは特にDisposeする必要もないです。

の理由により、MemoryStreamの変数は単にDimで宣言すればいい、ということですね。

色々と勉強になりました。
今後ともどうぞよろしくお願いします。
引用返信 編集キー/
■78579 / inTopicNo.6)  Re[5]: マルチtiff内の画像の保存でGDI+汎用エラー
□投稿者/ ゲート (4回)-(2016/01/27(Wed) 10:09:34)
解決済みをつけるのを忘れました。
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -