* Add the analysis window.
[master-thesis.git] / Parasitemia / Parasitemia / GUI / PiaZ.fs
1 // ParasitemIA Zipped file format.
2 module Parasitemia.GUI.PiaZ
3
4 open System
5 open System.Windows
6 open System.IO
7 open System.IO.Compression
8
9 open FSharp.Data
10
11 open Emgu.CV
12 open Emgu.CV.Structure
13
14 open Types
15
16 let extension = ".piaz"
17 let filter = "PIA|*.piaz"
18
19 type FileData = {
20 sources: SourceImage list
21 patientID: string }
22
23 // The json type associated to a source image.
24 type JSONSourceImage = JsonProvider<"""
25 {
26 "RBCRadius" : 32.5,
27 "dateLastAnalysis" : 1.5,
28 "rbcs": [
29 {
30 "num": 1,
31 "infected": true,
32 "setManually": false,
33 "posX" : 42.5,
34 "posY" : 42.5,
35 "width" : 10.5,
36 "height" : 10.5,
37 "stainArea" : 10
38 }
39 ]
40 }
41 """>
42
43 // The json type associated to a file.
44 type JSONMainInformation = JsonProvider<"""
45 {
46 "patientID": "1234abcd"
47 }
48 """>
49
50 let mainFilename = "info.json"
51 let imageExtension = ".tiff"
52
53 let save (filePath: string) (data: FileData) =
54 use file = ZipFile.Open(filePath, ZipArchiveMode.Update)
55
56 for e in List.ofSeq file.Entries do // 'ofSeq' to not iterate a collection currently modified.
57 e.Delete()
58
59 // Main JSON file.
60 let mainJSON = JSONMainInformation.Root(data.patientID)
61 let mainFile = file.CreateEntry(mainFilename, CompressionLevel.Fastest)
62 use mainFileWriter = new StreamWriter(mainFile.Open())
63 mainJSON.JsonValue.WriteTo(mainFileWriter, JsonSaveOptions.None)
64
65 // Write each images and the associated information.
66 for imgSrc in data.sources do
67 let imgFilename = (string imgSrc.num) + imageExtension
68 let imgEntry = file.CreateEntry(imgFilename, CompressionLevel.NoCompression) // FIXME: It seems a compression is applied to this file despite of the 'NoCompression' flag.
69 imgSrc.img.ToBitmap().Save(imgEntry.Open(), System.Drawing.Imaging.ImageFormat.Tiff)
70
71 let imgJSON =
72 JSONSourceImage.Root(decimal imgSrc.rbcRadius,
73 decimal <| imgSrc.dateLastAnalysis.ToFileTimeUtc(),
74 [| for rbc in imgSrc.rbcs ->
75 JSONSourceImage.Rbc(
76 rbc.num,
77 rbc.infected, rbc.setManually,
78 decimal rbc.center.X, decimal rbc.center.Y, decimal rbc.size.Width, decimal rbc.size.Height,
79 rbc.infectedArea) |])
80
81 let imgJSONEntry = file.CreateEntry(imgFilename + ".json", CompressionLevel.Fastest)
82 use imgJSONFileWriter = new StreamWriter(imgJSONEntry.Open())
83 imgJSON.JsonValue.WriteTo(imgJSONFileWriter, JsonSaveOptions.None)
84
85
86 let load (filePath: string) : FileData =
87 use file = ZipFile.Open(filePath, ZipArchiveMode.Read)
88
89 let mainFile = file.GetEntry(mainFilename)
90 let mainJSON = JSONMainInformation.Load(mainFile.Open())
91
92 let sources = [
93 let mutable imgNum = 0
94 for imgEntry in file.Entries do
95 let filename = imgEntry.Name
96 if filename.EndsWith(imageExtension)
97 then
98 let img = new Image<Bgr, byte>(new System.Drawing.Bitmap(imgEntry.Open(), false)) // FIXME: Should we dispose the bitmap?
99 imgNum <- imgNum + 1
100 let imgJSONEntry = file.GetEntry(filename + ".json")
101 let imgJSON = JSONSourceImage.Load(imgJSONEntry.Open())
102 yield { num = imgNum
103 rbcRadius = float imgJSON.RbcRadius
104 dateLastAnalysis = DateTime.FromFileTimeUtc(int64 imgJSON.DateLastAnalysis)
105 img = img
106 rbcs = [ for rbc in imgJSON.Rbcs ->
107 { num = rbc.Num;
108 infected = rbc.Infected; setManually = rbc.SetManually;
109 center = Point(float rbc.PosX, float rbc.PosY); size = Size(float rbc.Width, float rbc.Height);
110 infectedArea = rbc.StainArea } ] } ]
111 { sources = sources; patientID = mainJSON.PatientId }