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