// ParasitemIA Zipped file format. module Parasitemia.GUI.PiaZ open System open System.Windows open System.IO open System.IO.Compression open FSharp.Data open Emgu.CV open Emgu.CV.Structure open Types let extension = ".piaz" let filter = "PIA|*.piaz" type FileData = { sources: SourceImage list patientID: string } // The json type associated to a source image. type JSONSourceImage = JsonProvider<""" { "RBCRadius" : 32.5, "dateLastAnalysis" : 1.5, "rbcs": [ { "num": 1, "infected": true, "setManually": false, "posX" : 42.5, "posY" : 42.5, "width" : 10.5, "height" : 10.5, "stainArea" : 10 } ] } """> // The json type associated to a file. type JSONMainInformation = JsonProvider<""" { "patientID": "1234abcd" } """> let mainFilename = "info.json" let imageExtension = ".tiff" let save (filePath: string) (data: FileData) = 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 mainJSON = JSONMainInformation.Root(data.patientID) let mainFile = file.CreateEntry(mainFilename, CompressionLevel.Fastest) use mainFileWriter = new StreamWriter(mainFile.Open()) mainJSON.JsonValue.WriteTo(mainFileWriter, JsonSaveOptions.None) // Write each images and the associated information. for imgSrc in data.sources do let imgFilename = (string imgSrc.num) + imageExtension let imgEntry = file.CreateEntry(imgFilename, CompressionLevel.NoCompression) // FIXME: It seems a compression is applied to this file despite of the 'NoCompression' flag. imgSrc.img.ToBitmap().Save(imgEntry.Open(), System.Drawing.Imaging.ImageFormat.Tiff) let imgJSON = JSONSourceImage.Root(decimal imgSrc.rbcRadius, decimal <| imgSrc.dateLastAnalysis.ToFileTimeUtc(), [| for rbc in imgSrc.rbcs -> JSONSourceImage.Rbc( rbc.num, rbc.infected, rbc.setManually, decimal rbc.center.X, decimal rbc.center.Y, decimal rbc.size.Width, decimal rbc.size.Height, rbc.infectedArea) |]) let imgJSONEntry = file.CreateEntry(imgFilename + ".json", CompressionLevel.Fastest) use imgJSONFileWriter = new StreamWriter(imgJSONEntry.Open()) imgJSON.JsonValue.WriteTo(imgJSONFileWriter, JsonSaveOptions.None) let load (filePath: string) : FileData = use file = ZipFile.Open(filePath, ZipArchiveMode.Read) let mainFile = file.GetEntry(mainFilename) let mainJSON = JSONMainInformation.Load(mainFile.Open()) let sources = [ let mutable imgNum = 0 for imgEntry in file.Entries do let filename = imgEntry.Name if filename.EndsWith(imageExtension) then let img = new Image(new System.Drawing.Bitmap(imgEntry.Open(), false)) // FIXME: Should we dispose the bitmap? imgNum <- imgNum + 1 let imgJSONEntry = file.GetEntry(filename + ".json") let imgJSON = JSONSourceImage.Load(imgJSONEntry.Open()) yield { num = imgNum rbcRadius = float imgJSON.RbcRadius dateLastAnalysis = DateTime.FromFileTimeUtc(int64 imgJSON.DateLastAnalysis) img = img rbcs = [ for rbc in imgJSON.Rbcs -> { num = rbc.Num; infected = rbc.Infected; setManually = rbc.SetManually; center = Point(float rbc.PosX, float rbc.PosY); size = Size(float rbc.Width, float rbc.Height); infectedArea = rbc.StainArea } ] } ] { sources = sources; patientID = mainJSON.PatientId }