// 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
fileVersion: int
}
// 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
healthyRBCBrightness: float32 // 0 to 1.
infectedRBCBrightness: float32 // 0 to 1.
}
type DocumentData = {
patientID: string
images: SourceImage list
}
let mainEntryName = "info.json"
let imageExtension = ".tiff"
let currentFileVersion = 1
///
/// 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({ patientID = data.patientID; fileVersion = currentFileVersion }))
// 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
healthyRBCBrightness = srcImg.healthyRBCBrightness
infectedRBCBrightness = srcImg.infectedRBCBrightness }))
let updateDocumentData (fromVersion: int) (toVersion: int) (data: DocumentData) : DocumentData =
for v in fromVersion + 1 .. toVersion do
match v with
| 1 -> // Version 0 -> 1 : set initial brightness for rbc.
data.images |> List.iter (fun i -> i.healthyRBCBrightness <- 1.f; i.infectedRBCBrightness <- 1.f)
| _ -> ()
data
///
/// 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())
updateDocumentData info.fileVersion currentFileVersion
{ patientID = info.patientID
images = [ let mutable imgNum = 0
for imgEntry in file.Entries do
if imgEntry.Name.EndsWith(imageExtension)
then
use bitmap = new System.Drawing.Bitmap(imgEntry.Open(), false)
let img = new Image(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
healthyRBCBrightness = imgInfo.healthyRBCBrightness
infectedRBCBrightness = imgInfo.infectedRBCBrightness } ] }