複数画像(BitmapSource)と
シリアライズした文字列(String)や数値(Integerとか)を1つのZipファイルにする
けど
今回は
TIFFと
pngどちらかの画像に変換してZipファイルに収めることにした
文字列(String)や数値(Integerとか)の部分は前回の
これと同じ
回転角度の数値は
シリアライズしてdata.binとういう名前で保存
画像と回転角度をまとめてZipファイルにして
これを読み込んで再現したのが中央と右側の画像
Zipファイルはアプリの実行ファイルと同じフォルダに作成
savePng.zipとsaveTiff.zipがそれ
中の状態は
回転角度を収めたdata.bin
PNGは保存する画像の枚数分の
PNGファイルと回転角度のdata.bin
以上が結果
sp1、sp2、sp3と名前をつけたStackPanelを3つ横に並べただけ
Imports System.IO
Imports System.IO.Compression
Class MainWindow
Private bitmapList As New List(Of BitmapSource)
Private DataList As New List(Of SaveData)
Private Sub initial()
Dim fileName1 As String = "D:\ブログ用\テスト用画像\hueRect030.png"
Dim fileName2 As String = "D:\ブログ用\テスト用画像\hueRect210.png"
DataList.Add(New SaveData With {.angle = 30, .name = fileName1})
DataList.Add(New SaveData With {.angle = 12.345, .name = fileName2})
bitmapList.Add(New BitmapImage(New Uri(fileName1)))
bitmapList.Add(New BitmapImage(New Uri(fileName2)))
For i As Integer = 0 To bitmapList.Count - 1
Dim img As New Image
With img
.Source = bitmapList(i)
.RenderTransform = New RotateTransform(DataList(i).angle)
.Name = "image" & i
.Stretch = Stretch.None
End With
sp1.Children.Add(img)
Next
End Sub
Private Sub SaveTiff()
Dim encoder As New TiffBitmapEncoder
Dim frame As BitmapFrame
For i As Integer = 0 To bitmapList.Count - 1
frame = BitmapFrame.Create(bitmapList(i))
encoder.Frames.Add(frame)
Next
Dim zipPath As String = My.Application.Info.DirectoryPath & "\" & "saveTiff.zip"
Using zipStream As Stream = File.Create(zipPath)
Using archive As New ZipArchive(zipStream, ZipArchiveMode.Create)
Dim entry As ZipArchiveEntry = archive.CreateEntry("bmp.tiff")
Using entryStream As Stream = entry.Open
Using ms As New MemoryStream
encoder.Save(ms)
ms.Position = 0
ms.CopyTo(entryStream)
End Using
End Using
Using msAngle As New MemoryStream
Dim bf As New Runtime.Serialization.Formatters.Binary.BinaryFormatter
bf.Serialize(msAngle, DataList)
entry = archive.CreateEntry("data.bin")
Using entryStreamAngle As Stream = entry.Open
msAngle.Position = 0
msAngle.CopyTo(entryStreamAngle)
End Using
End Using
End Using
End Using
End Sub
Private Sub LoadTiff()
Dim zipPath As String = My.Application.Info.DirectoryPath & "\" & "saveTiff.zip"
Dim bitmapListFromZip As New List(Of BitmapSource)
Dim DataListFromZip As New List(Of SaveData)
Using zipStream As Stream = File.OpenRead(zipPath)
Using archive As New ZipArchive(zipStream, ZipArchiveMode.Read)
Dim entry As ZipArchiveEntry = archive.GetEntry("bmp.tiff")
Using entryStream = entry.Open
Using ms As New MemoryStream
entryStream.CopyTo(ms)
ms.Position = 0
Dim decorder As New TiffBitmapDecoder(ms, BitmapCreateOptions.None, BitmapCacheOption.OnLoad)
For i As Integer = 0 To bitmapList.Count - 1
bitmapListFromZip.Add(decorder.Frames(i))
Next
End Using
End Using
entry = archive.GetEntry("data.bin")
Using entryStream As Stream = entry.Open
Using ms As New MemoryStream
entryStream.CopyTo(ms)
ms.Position = 0
Dim bf As New Runtime.Serialization.Formatters.Binary.BinaryFormatter
DataListFromZip = bf.Deserialize(ms)
End Using
End Using
End Using
End Using
For i As Integer = 0 To bitmapListFromZip.Count - 1
Dim img As New Image
With img
.Source = bitmapListFromZip(i)
.RenderTransform = New RotateTransform(DataListFromZip(i).angle)
.Name = "image" & i
.Stretch = Stretch.None
End With
sp2.Children.Add(img)
Next
End Sub
Private Sub SavePng()
Dim zipPath As String = My.Application.Info.DirectoryPath & "\" & "savePng.zip"
Using zipStream As Stream = File.Create(zipPath)
Using archive As New ZipArchive(zipStream, ZipArchiveMode.Create)
For i As Integer = 0 To bitmapList.Count - 1
Dim encoder As New PngBitmapEncoder
Dim fileName As String = i & ".png"
Dim entry As ZipArchiveEntry = archive.CreateEntry(fileName)
Dim frame As BitmapFrame = BitmapFrame.Create(bitmapList(i))
encoder.Frames.Add(frame)
Using entryStream As Stream = entry.Open
Using ms As New MemoryStream
encoder.Save(ms)
ms.Position = 0
ms.CopyTo(entryStream)
End Using
End Using
Next
Using msAngle As New MemoryStream
Dim bf As New Runtime.Serialization.Formatters.Binary.BinaryFormatter
bf.Serialize(msAngle, DataList)
Dim entry As ZipArchiveEntry = archive.CreateEntry("data.bin")
Using entryStreamAngle As Stream = entry.Open
msAngle.Position = 0
msAngle.CopyTo(entryStreamAngle)
End Using
End Using
End Using
End Using
End Sub
Private Sub LoadPng()
Dim zipPath As String = My.Application.Info.DirectoryPath & "\" & "savePng.zip"
Dim bitmapListFromZip As New List(Of BitmapSource)
Dim DataListFromZip As New List(Of SaveData)
Using zipStream As Stream = File.OpenRead(zipPath)
Using archive As New ZipArchive(zipStream, ZipArchiveMode.Read)
For i As Integer = 0 To bitmapList.Count - 1
Dim fileName As String = i & ".png"
Dim entryB As ZipArchiveEntry = archive.GetEntry(fileName)
Using entryStream = entryB.Open
Using ms As New MemoryStream
entryStream.CopyTo(ms)
ms.Position = 0
Dim decorder As New PngBitmapDecoder(ms, BitmapCreateOptions.None, BitmapCacheOption.OnLoad)
bitmapListFromZip.Add(decorder.Frames(0))
End Using
End Using
Next
Dim entry As ZipArchiveEntry = archive.GetEntry("data.bin")
Using entryStream As Stream = entry.Open
Using ms As New MemoryStream
entryStream.CopyTo(ms)
ms.Position = 0
Dim bf As New Runtime.Serialization.Formatters.Binary.BinaryFormatter
DataListFromZip = bf.Deserialize(ms)
End Using
End Using
End Using
End Using
For i As Integer = 0 To bitmapListFromZip.Count - 1
Dim img As New Image
With img
.Source = bitmapListFromZip(i)
.RenderTransform = New RotateTransform(DataListFromZip(i).angle)
.Name = "image" & i
.Stretch = Stretch.None
End With
sp3.Children.Add(img)
Next
End Sub
Private Sub MainWindow_Initialized(sender As Object, e As EventArgs) Handles Me.Initialized
Call initial()
Call SaveTiff()
Call LoadTiff()
Call SavePng()
Call LoadPng()
End Sub
End Class
<Serializable>
Public Class SaveData
Public Property angle As Double
Public Property name As String
End Class
画像以外の情報を入れておくクラス
Nameは文字列
Zipファイルを扱うのでSystem.IO.Compressionを参照に追加しておく
追加方法は前回の記事
BitmapListに元の画像として表示しているBitmapSourceを全部入れておく
DataListはさっきのsaveDataクラスを全部入れておくリスト
ホントはこのふたつを一つにまとめたい
アプリ起動時、Initializedイベント
準備
回転角度を適当に決めてSaveDataクラスを作ってリストに追加
表示する画像の指定や回転角度はさっきのリストを使って設定
作成したImageはsp1に追加して表示
Dim b as Byte()~
Dim ta as Byte()~
これ要らない
それ以外は前回とほとんど同じかなあ
違うのはZipに入れるのが画像とSaveDataの2つに増えたから
ZipArchiveEntryも2つになったこと
保存したZipファイルを読み込んで画像表示
複数画像を収めた
TIFF画像からの画像取り出しは普通にTiffBitmapDecoderに
読みこめば、そのFramesの中にBitmapSourceが順番に入っているのでそれを取り出すだけ
Tiffと違うのは元の画像枚数分の
PNG画像を作成して、連番の名前を付けてZipに入れていること
PNGでもFrames.Add(BitmapFrame)でどんどん画像追加できて
保存もできたんだけど、これを読み込んでも取り出せなかったので
枚数分作成している
Tiffと違うのは画像取り出しの時に名前を指定して取り出しているところ
Dim fileName As String = i & ".
png"
Dim entryB As ZipArchiveEntry = archive.GetEntry(fileName)
Tiffは連番のIndexで指定しているからこの部分の処理は
Tiffのほうが早そう
一長一短でどちらにしようか迷うけど
TIFFにしようかなあ
ファイルサイズ(KB)
122 前回の文字列に変換してZip
こうしてみると
PNGと
TIFFのサイズの違いは文字列に変換と比べると誤差程度
写真画像ならまた違ってくるんだろうけど、文字列に変換はどうしても
シリアライズしたい時しか出番はなさそう
目的のPixtack紫陽花2ndの編集状態を保存しておいて、次回の起動時に編集状態を再現したいってのは今回のでできるはず、なんだけどあっちは回転角度とかはスライダーとも連携しているから、なんか複雑なことになりそう、DataBindingとか使えればスッキリできできそうかなってのもある、うーん
今回のコード
関連記事