【Silverlight】将WriteableBitmap保存为24位位图

来自ampedZ的博客园,原文地址:http://www.cnblogs.com/ampedZ/p/GetBMP24Stream.html

Silverlight没有提供图片保存功能,WriteableBitmap也只能将流Set而无法Get

下列代码实现将WriteableBitmap保存为24位位图,主要是通过将WriteableBitmapPixels按照BMP规范写入。

方法模块
Option Explicit On
Option Strict Off

Imports System.IO
Imports System.Windows.Media.Imaging

Module ampedZModule

    ''' <summary>返回一个流,该流为由可写位图生成的24位BMP流。</summary>
    ''' <param name="Source">可写位图</param>
    Public Function GetBMP24Stream(ByRef Source As WriteableBitmap) As Stream
        Dim Result As MemoryStream = New MemoryStream
        Dim w As Integer = Source.PixelWidth * 3
        If w Mod 4 <> 0 Then w = (w \ 4 + 1) * 4
        Dim h As Integer = Source.PixelHeight
        Dim bw As BinaryWriter = New BinaryWriter(Result)
        'Bitmap File Header
        bw.Write({AscW("B"), AscW("M")})                        'bfType
        bw.Write(BytesFromInt32(w * h + 54, 4, True))           'bfSize
        bw.Write({&H0, &H0})                                    'bfReserved1
        bw.Write({&H0, &H0})                                    'bfReserved2
        bw.Write(BytesFromInt32(54, 4, True))                   'bfOffBits
        'Bitmap Information Header
        bw.Write(BytesFromInt32(40, 4, True))                   'biSize
        bw.Write(BytesFromInt32(Source.PixelWidth, 4, True))    'biWidth
        bw.Write(BytesFromInt32(Source.PixelHeight, 4, True))   'biHeight
        bw.Write(BytesFromInt32(1, 2, True))                    'biPlanes
        bw.Write(BytesFromInt32(24, 2, True))                   'biBitCount
        bw.Write(BytesFromInt32(0, 4, True))                    'biCompression
        bw.Write(BytesFromInt32(w * h, 4, True))                'biSizeImage
        bw.Write(BytesFromInt32(0, 4, True))                    'biXPelsPerMeter
        bw.Write(BytesFromInt32(0, 4, True))                    'biYPelsPerMeter
        bw.Write(BytesFromInt32(0, 4, True))                    'biClrUsed
        bw.Write(BytesFromInt32(0, 4, True))                    'biClrImportant
        'Color Table
        'Bitmap Data
        For y As Integer = Source.PixelHeight - 1 To 0 Step -1
            Dim b(w - 1) As Byte
            For x As Integer = 0 To Source.PixelWidth - 1
                Dim c As Color = ColorFromInt32(Source.Pixels(Source.PixelWidth * y + x))
                b(x * 3 + 0) = c.B
                b(x * 3 + 1) = c.G
                b(x * 3 + 2) = c.R
            Next
            bw.Write(b)
        Next
        Result.Seek(0, SeekOrigin.Begin)
        Return Result
    End Function

    ''' <summary>返回一个字节数组,该字节数组从32位整数转换而来。</summary>
    ''' <param name="Source">被转换的32位整数</param>
    ''' <param name="Length">字节数组的长度</param>
    ''' <param name="IsReverse">字节数组的排列是否反转</param>
    Public Function BytesFromInt32(ByVal Source As Integer, ByVal Length As Integer, ByVal IsReverse As Boolean) As Byte()
        If Source > Math.Pow(256, Length) - 1 Then Throw New NotImplementedException()
        Dim Result(Length - 1) As Byte
        If Source = 0 Then Return Result
        Dim r As Integer = Source
        For i As Integer = Length - 1 To 0 Step -1
            Dim t As Byte = r \ (Math.Pow(256, i))
            If t <> 0 Then
                If IsReverse = False Then
                    Result(Length - 1 - i) = t
                Else
                    Result(i) = t
                End If
                r -= Math.Pow(256, i) * t
            End If
        Next
        Return Result
    End Function

    ''' <summary>返回一个颜色,该颜色由32位整数转换而来。</summary>
    ''' <param name="Int32">32位整数</param>
    Public Function ColorFromInt32(ByVal Int32 As Integer) As Color
        Dim b As Byte() = BitConverter.GetBytes(Int32)
        Return Color.FromArgb(b(3), b(2), b(1), b(0))
    End Function

End Module
前台代码
<UserControl x:Class="SilverlightApplication1.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Button x:Name="SavePicButton" Content="SavePic"/>
</UserControl>
后台代码
Option Explicit On
Option Strict Off

Imports System.IO
Imports System.Windows.Media.Imaging

Partial Public Class MainPage
    Inherits UserControl

    Public Sub New()
        InitializeComponent()
    End Sub

    Private Sub SavePicButton_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles SavePicButton.Click
        Dim s As SaveFileDialog = New SaveFileDialog With {.Filter = "24位位图 (*.bmp)|*.bmp", .DefaultExt = "bmp"}
        If s.ShowDialog = True Then
            Using fs As Stream = s.OpenFile()
                Using ms As MemoryStream = GetBMP24Stream(New WriteableBitmap(32, 32))
                    ms.CopyTo(fs)
                End Using
            End Using
        End If
    End Sub

End Class

 

posted @ 2012-12-29 11:40  ampedZ  阅读(1073)  评论(0)    收藏  举报