【Silverlight】将WriteableBitmap保存为24位位图
来自ampedZ的博客园,原文地址:http://www.cnblogs.com/ampedZ/p/GetBMP24Stream.html
Silverlight没有提供图片保存功能,WriteableBitmap也只能将流Set而无法Get。
下列代码实现将WriteableBitmap保存为24位位图,主要是通过将WriteableBitmap的Pixels按照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