// 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" /// /// Save a document in a give file path. The file may already exist. /// /// /// /// If the file cannot be written 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 })) /// /// Load document from a give file path. /// /// /// If the file cannot be read 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(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(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(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 } ] }