d4ea46fa6eb062492bc5b1624e9555f68dd4ebb8
[master-thesis.git] / Parasitemia / ParasitemiaUI / PiaZ.fs
1 // ParasitemIA Zipped document format.
2 module ParasitemiaUI.PiaZ
3
4 open System
5 open System.Windows
6 open System.IO
7 open System.IO.Compression
8
9 open Emgu.CV
10 open Emgu.CV.Structure
11
12 open Newtonsoft.Json
13 open Newtonsoft.Json.Converters
14
15 open Types
16
17 let extension = ".piaz"
18 let filter = "PIA|*.piaz"
19
20 // Information associated to a document.
21 type JSONInformation = {
22 patientID: string
23 }
24
25 // Information associated to each images.
26 type JSONSourceImage = {
27 num: int
28 RBCRadius: float32 // The RBC Radius found by granulometry.
29 parameters: ParasitemiaCore.Config.Parameters
30 dateLastAnalysis: DateTime
31 rbcs: RBC List
32 }
33
34 type DocumentData = {
35 patientID: string
36 images: SourceImage list
37 }
38
39 let mainEntryName = "info.json"
40 let imageExtension = ".tiff"
41
42 /// <summary>
43 /// Save a document in a give file path. The file may already exist.
44 /// </summary>
45 /// <param name="filePath"></param>
46 /// <param name="data"></param>
47 /// <exception cref="System.IOException">If the file cannot be written</exception>
48 let save (filePath: string) (data: DocumentData) =
49 use file = ZipFile.Open(filePath, ZipArchiveMode.Update)
50
51 for e in List.ofSeq file.Entries do // 'ofSeq' to not iterate a collection currently modified.
52 e.Delete()
53
54 // Main JSON file.
55 let mainEntry = file.CreateEntry(mainEntryName, CompressionLevel.Fastest)
56 use mainEntryWriter = new StreamWriter(mainEntry.Open())
57 mainEntryWriter.Write(JsonConvert.SerializeObject({ JSONInformation.patientID = data.patientID }))
58
59 // Write each images and the associated information.
60 for srcImg in data.images do
61 let imgFilename = (string srcImg.num) + imageExtension
62 let imgEntry = file.CreateEntry(imgFilename, CompressionLevel.NoCompression) // FIXME: It seems a compression is applied to this file despite of the 'NoCompression' flag.
63 srcImg.img.ToBitmap().Save(imgEntry.Open(), System.Drawing.Imaging.ImageFormat.Tiff)
64
65 let imgJSONEntry = file.CreateEntry(imgFilename + ".json", CompressionLevel.Fastest)
66 use imgJSONFileWriter = new StreamWriter(imgJSONEntry.Open())
67 imgJSONFileWriter.Write(JsonConvert.SerializeObject({ num = srcImg.num; RBCRadius = srcImg.config.RBCRadius.Pixel; parameters = srcImg.config.Parameters; dateLastAnalysis = srcImg.dateLastAnalysis; rbcs = srcImg.rbcs }))
68
69 /// <summary>
70 /// Load document from a give file path.
71 /// </summary>
72 /// <param name="filePath"></param>
73 /// <exception cref="System.IOException">If the file cannot be read</exception>
74 let load (filePath: string) : DocumentData =
75 use file = ZipFile.Open(filePath, ZipArchiveMode.Read)
76
77 let mainEntry = file.GetEntry(mainEntryName)
78 use mainEntryReader = new StreamReader(mainEntry.Open())
79 let info = JsonConvert.DeserializeObject<JSONInformation>(mainEntryReader.ReadToEnd())
80
81 { patientID = info.patientID
82 images = [ let mutable imgNum = 0
83 for imgEntry in file.Entries do
84 if imgEntry.Name.EndsWith(imageExtension)
85 then
86 let img = new Image<Bgr, byte>(new System.Drawing.Bitmap(imgEntry.Open(), false)) // FIXME: Should we dispose the bitmap?
87 imgNum <- imgNum + 1
88 let imgEntry = file.GetEntry(imgEntry.Name + ".json")
89 use imgEntryFileReader = new StreamReader(imgEntry.Open())
90 let imgInfo = JsonConvert.DeserializeObject<JSONSourceImage>(imgEntryFileReader.ReadToEnd())
91 let config = ParasitemiaCore.Config.Config(imgInfo.parameters)
92 config.SetRBCRadius imgInfo.RBCRadius
93 yield { num = imgNum
94 config = config
95 dateLastAnalysis = imgInfo.dateLastAnalysis
96 img = img
97 rbcs = imgInfo.rbcs } ] }