VB2008で半透明化した画像を保存する方法

タグの編集
投稿者 モル  (社会人) 投稿日時 2009/12/4 20:52:36
少し前にコントラストのやり方を聞いたモルです。
今回ご教授願いたいのは「半透明化を行って表示したPictureBoxの画像を透明処理が行われたまま保存するには?」というものです。

中学校様のサンプルに載せてありました半透明化のプログラムを少し加工してますが、
    Private Sub Form1_Load(ByVal sender As System.ObjectByVal e As System.EventArgs) Handles MyBase.Load
        Dim MImage As Image = Image.FromFile("C:\Test.JPG")
        With PictureBox1
            .Width = MImage.Width
            .Height = MImage.Height
        End With

        Dim g As Graphics = AutoGraphics(PictureBox1)
        Dim cm As New System.Drawing.Imaging.ColorMatrix()
        cm.Matrix00 = 1
        cm.Matrix11 = 1
        cm.Matrix22 = 1
        cm.Matrix33 = 0.5F
        cm.Matrix44 = 1
        Dim ia As New System.Drawing.Imaging.ImageAttributes()
        ia.SetColorMatrix(cm)
        g.DrawImage(MImage, New Rectangle(0, 0, MImage.Width, MImage.Height), _
                                0, 0, MImage.Width, MImage.Height, GraphicsUnit.Pixel, ia)
        'リソースを開放する 
        MImage.Dispose() : g.Dispose()
End Sub

    Private Function AutoGraphics(ByVal picSource As PictureBox) As Graphics
        If picSource.Image Is Nothing Then
            picSource.Image = New Bitmap(picSource.ClientRectangle.Width, picSource.ClientRectangle.Height)
        End If
        Return Graphics.FromImage(picSource.Image)
    End Function

上記のプログラムにて、半透明化させて表示しているPictureBox1の画像を保存したいのです。

PictureBox1.Image.Save("C:\aa.JPG")
とやっても半透明じゃない元の画像のまま保存されてしまいます。
透明化処理を行った画像の保存の方法をお教え下さい。
お願いします。

ちなみにお教えくださったコントラストでの保存は、キチンとコントラストがかかったまま保存できました。
投稿者 匿名  (社会人) 投稿日時 2009/12/5 04:11:31
http://www.atmarkit.co.jp/fdotnet/dotnettips/020savebmp/savebmp.html
このへんが参考になるかも
投稿者 葉月  (社会人) 投稿日時 2009/12/5 05:17:42
サンプルもなく試していないのでご了承ください。

保存の際にアルファチャネルが入っていないので、半透明にならないと考えられます。
http://ja.wikipedia.org/wiki/%E3%82%A2%E3%83%AB%E3%83%95%E3%82%A1%E3%83%81%E3%83%A3%E3%83%B3%E3%83%8D%E3%83%AB

今のままだと24bit色で保存されるため、以下のBitmap コンストラクタを使う必要があります。
http://msdn.microsoft.com/ja-jp/library/3z132tat.aspx

それから、32bitのFormat32bppArgbを使用する必要があると思います。
http://msdn.microsoft.com/ja-jp/library/system.drawing.imaging.pixelformat.aspx

これだけでOKかはわかりません。
サンプルを提示されているので、私もサンプルを載せたいところですが――
私も試したことがなく、私用を優先しないといけないため見送ります。
後で時間があれば、サンプルを作るかもしれません。
投稿者 cupid  (社会人) 投稿日時 2009/12/5 08:05:12
実際に試した事は少ないのですが、想像するに、透明画像とか、半透明とか、
それは画像自体の問題というより、下敷きと協業するものと思うのです。
透過GIFの場合は間違いなくそうです。画像側にも透明の設定は必要ですが、
それは常に透明とは限らず、IEなどの上に置いた場合のみ透明ですから。

半透明については、多分仕組みが違うはずです。また、JPGでは保存でない
でしょう。32ビット型のBMPなら保存できるかもしれませんが、そうすると
画像ソフトによっては読めないケースも出て来るでしょう。
MSのペイントその他なら読めましょうが、OSが古いと読めないはずです。
投稿者 葉月  (社会人) 投稿日時 2009/12/5 09:40:25
提示されたサンプルをいじっただけですが、少し時間を取ってサンプルにしました。
フィールド(定数)の部分は、変える必要があります。

Win7でしか確認していませんが、32bitカラーはOS付属の
ペイントとフォットビューアで透過された状態で開けます。
Bitmapしか試していません。
Vista前は不明です。

■サンプル
Public Class Form1

#Region "フィールド(定数)"

    ' 画像のパス 
    Private Const STRING_IMAGE_PATH As String = "C:\Users\owner\Pictures\test.bmp"
    ' 画像の保存パス 
    Private Const STRING_SAVE_PATH As String = "C:\Users\owner\Pictures\test2.bmp"

#End Region


    Private Sub Form1_Load(ByVal sender As System.ObjectByVal e As System.EventArgs) Handles MyBase.Load
        Using img As Image = Image.FromFile(STRING_IMAGE_PATH)

            With PictureBox1
                .Width = img.Width
                .Height = img.Height
            End With

            ' 幅 
            Dim iWidth As Integer = PictureBox1.ClientRectangle.Width
            ' 高さ 
            Dim iHeight As Integer = PictureBox1.ClientRectangle.Height

            If PictureBox1.Image Is Nothing Then
                PictureBox1.Image = New Bitmap(iWidth, iHeight, System.Drawing.Imaging.PixelFormat.Format32bppArgb)
            End If

            Using g As Graphics = Graphics.FromImage(PictureBox1.Image)
                ' 閾値の変更 
                Dim matrix As New System.Drawing.Imaging.ColorMatrix()
                matrix.Matrix00 = 1
                matrix.Matrix11 = 1
                matrix.Matrix22 = 1
                matrix.Matrix33 = 0.5F
                matrix.Matrix44 = 1

                ' 閾値を設定 
                Dim attr As New System.Drawing.Imaging.ImageAttributes()
                attr.SetColorMatrix(matrix)
                g.DrawImage(img, New Rectangle(0, 0, img.Width, img.Height), _
                                        0, 0, img.Width, img.Height, GraphicsUnit.Pixel, attr)
                ' 保存 
                PictureBox1.Image.Save(STRING_SAVE_PATH)
            End Using
        End Using
    End Sub

End Class

投稿者 匿名  (社会人) 投稿日時 2009/12/5 18:28:20
モルさんのコードでも保存できています。(間違いではないです)
PictureBox1.Image.Save("C:\aa.JPG")

ただ、cupidさんや葉月さんのいわれているとおり読める環境が整っていないと無理なようです
投稿者 トマト  (小学生) 投稿日時 2009/12/5 20:46:19
半透明ってPNGで保存すればうまくいきそうな気がします・・・。
投稿者 (削除されました)  () 投稿日時 2009/12/5 23:00:25
(削除されました)
投稿者 葉月  (社会人) 投稿日時 2009/12/5 23:31:24
私はVS2008Sp1を使っていますが――
Bitmap(Integer, Integer)コンストラクタの方でも透過されますね。
上記のコンストラクタだと、PixelFormat.Format24bppRgbを適用すると思っていたので、
勘違いしていました。
匿名さんの発言で気づきました。ありがとうございます。

■サンプル
 PictureBox1.Image = New Bitmap(iWidth, iHeight, System.Drawing.Imaging.PixelFormat.Format32bppPArgb)
                'PictureBox1.Image = New Bitmap(iWidth, iHeight, System.Drawing.Imaging.PixelFormat.Format24bppRgb) 
                'PictureBox1.Image = New Bitmap(iWidth, iHeight, System.Drawing.Imaging.PixelFormat.Format32bppRgb) 



前に私が出したサンプルを利用し、コメントを入れ替えれば、透過ができる環境でも失敗する
のがわかります。
ただのRGBじゃだめで、一色追加されたARGBがアルファチャネル対応になるのがわかります。
ARGB対応の画像フォーマットで環境に適用できれば、読むことが可能だと推測できます。

ちなみにざっくりとですが、OSごとの対応状況も見ておきました。
Windows2000(SP4) ×
WindowsXP(SP3) ○
投稿者 モル  (社会人) 投稿日時 2009/12/7 18:00:28
匿名様、葉月様、cupid様、トマト様
貴重な時間を割いて回答&サンプル提示ありがとうございます。
質問させていただいておきながら週末ネット環境が無い所へ急遽行く事になりまして返答が出来ませんでした、すみません。

まだ一通り読ませていただいただけですが、これから頂いた意見を参考に試してみたいと思います。
取り急ぎ返答だけさせていただきました。
投稿者 モル  (社会人) 投稿日時 2009/12/7 19:21:04
早速提示された参考URLやサンプルを使わせていただいて実行してみました。
結果、キチンと透明化処理をされた画像を保存する事が出来ました!

サンプルまで載せていただいた葉月様、参考URLや案など載せていただきました匿名様、cupid様、トマト様、ありがとうございました。

私の環境
OS:WinXP SP2
VS2008SP1 VB6SP6