--- /dev/null
+// ParasitemIA Zipped document format.
+module ParasitemiaUI.PiaZ
+
+open System
+open System.Windows
+open System.IO
+open System.IO.Compression
+
+open Emgu.CV
+open Emgu.CV.Structure
+
+open Newtonsoft.Json
+open Newtonsoft.Json.Converters
+
+open Types
+
+let extension = ".piaz"
+let filter = "PIA|*.piaz"
+
+// Information associated to a document.
+type JSONInformation = {
+ patientID: string
+}
+
+// Information associated to each images.
+type JSONSourceImage = {
+ num: int
+ RBCRadius: float32 // The RBC Radius found by granulometry.
+ parameters: ParasitemiaCore.Config.Parameters
+ dateLastAnalysis: DateTime
+ rbcs: RBC List
+}
+
+type DocumentData = {
+ patientID: string
+ images: SourceImage list
+}
+
+let mainEntryName = "info.json"
+let imageExtension = ".tiff"
+
+/// <summary>
+/// Save a document in a give file path. The file may already exist.
+/// </summary>
+/// <param name="filePath"></param>
+/// <param name="data"></param>
+/// <exception cref="System.IOException">If the file cannot be written</exception>
+let save (filePath: string) (data: DocumentData) =
+ use file = ZipFile.Open(filePath, ZipArchiveMode.Update)
+
+ for e in List.ofSeq file.Entries do // 'ofSeq' to not iterate a collection currently modified.
+ e.Delete()
+
+ // Main JSON file.
+ let mainEntry = file.CreateEntry(mainEntryName, CompressionLevel.Fastest)
+ use mainEntryWriter = new StreamWriter(mainEntry.Open())
+ mainEntryWriter.Write(JsonConvert.SerializeObject({ JSONInformation.patientID = data.patientID }))
+
+ // Write each images and the associated information.
+ for srcImg in data.images do
+ let imgFilename = (string srcImg.num) + imageExtension
+ let imgEntry = file.CreateEntry(imgFilename, CompressionLevel.NoCompression) // FIXME: It seems a compression is applied to this file despite of the 'NoCompression' flag.
+ srcImg.img.ToBitmap().Save(imgEntry.Open(), System.Drawing.Imaging.ImageFormat.Tiff)
+
+ let imgJSONEntry = file.CreateEntry(imgFilename + ".json", CompressionLevel.Fastest)
+ use imgJSONFileWriter = new StreamWriter(imgJSONEntry.Open())
+ imgJSONFileWriter.Write(JsonConvert.SerializeObject({ num = srcImg.num; RBCRadius = srcImg.config.RBCRadius.Pixel; parameters = srcImg.config.Parameters; dateLastAnalysis = srcImg.dateLastAnalysis; rbcs = srcImg.rbcs }))
+
+/// <summary>
+/// Load document from a give file path.
+/// </summary>
+/// <param name="filePath"></param>
+/// <exception cref="System.IOException">If the file cannot be read</exception>
+let load (filePath: string) : DocumentData =
+ use file = ZipFile.Open(filePath, ZipArchiveMode.Read)
+
+ let mainEntry = file.GetEntry(mainEntryName)
+ use mainEntryReader = new StreamReader(mainEntry.Open())
+ let info = JsonConvert.DeserializeObject<JSONInformation>(mainEntryReader.ReadToEnd())
+
+ { patientID = info.patientID
+ images = [ let mutable imgNum = 0
+ for imgEntry in file.Entries do
+ if imgEntry.Name.EndsWith(imageExtension)
+ then
+ let img = new Image<Bgr, byte>(new System.Drawing.Bitmap(imgEntry.Open(), false)) // FIXME: Should we dispose the bitmap?
+ imgNum <- imgNum + 1
+ let imgEntry = file.GetEntry(imgEntry.Name + ".json")
+ use imgEntryFileReader = new StreamReader(imgEntry.Open())
+ let imgInfo = JsonConvert.DeserializeObject<JSONSourceImage>(imgEntryFileReader.ReadToEnd())
+ let config = ParasitemiaCore.Config.Config(imgInfo.parameters)
+ config.SetRBCRadius imgInfo.RBCRadius
+ yield { num = imgNum
+ config = config
+ dateLastAnalysis = imgInfo.dateLastAnalysis
+ img = img
+ rbcs = imgInfo.rbcs } ] }
\ No newline at end of file