Salome HOME
Copyright update 2020
[modules/med.git] / src / MEDCalc / tui / medimages.py
1 #  -*- coding: iso-8859-1 -*-
2 # Copyright (C) 2007-2020  CEA/DEN, EDF R&D
3 #
4 # This library is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU Lesser General Public
6 # License as published by the Free Software Foundation; either
7 # version 2.1 of the License, or (at your option) any later version.
8 #
9 # This library is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 # Lesser General Public License for more details.
13 #
14 # You should have received a copy of the GNU Lesser General Public
15 # License along with this library; if not, write to the Free Software
16 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17 #
18 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 #
20
21 # Author : Guillaume Boulant (EDF)
22
23 import sys
24 if sys.platform == "win32":
25   import MEDCouplingCompat as MC
26 else:
27   import medcoupling as MC
28
29 import MEDLoader as ML
30
31 from PIL import Image
32 from PIL import ImageOps
33 import numpy
34
35 class FieldBuilder:
36
37     def image2med(self, imageFilepath, medFilepath=None):
38
39         # Load the image file in a numpy array using PIL.
40         img=Image.open(imageFilepath)
41         imgbw=ImageOps.grayscale(img)
42         # WARN: We keep only the grayscale. Maybe, it could be useful
43         # to get the RGB scales each on one component of the field.
44
45         # Creating a cartesian mesh with a grid of the size of the image
46         # The sizes defined the number of pixel in a direction, then the
47         # number of cells to create in the mesh in that direction.
48         width,height=imgbw.size
49         mesh=self.createMesh("grid_%sx%s"%(width,height),width,height)
50         field=self.createField("imagefield",mesh,imgbw)
51
52         # The MEDLoader can be used to save all the stuff in a med file. You
53         # just have to specify the field and the MEDLoader will save the
54         # underlying mesh.
55         createFromScratch=True
56         ML.WriteField(medFilepath,field,createFromScratch)
57
58     def createMesh(self, meshname, sizeX, sizeY):
59         """
60         Creating a cartesian mesh with a grid of the size of the image.
61         sizeX and sizeY should be respectively the width and height of the
62         image.
63         """
64         # >>>
65         # WARNING: remember the problem of tics and spaces. The data values
66         # are considered as values defined on cells. With size values in a
67         # direction, we have to create size+1 mesh nodes in that direction.
68         # <<<
69
70         # The mesh is created using MEDCoupling
71         cmesh=MC.MEDCouplingCMesh.New();
72         cmesh.setName(meshname)
73
74         # We use an arbitrary step between cells (the value does not matter)
75         stepX = 0.1
76         nbNodesX = sizeX+1
77         arrX = [float(i * stepX) for i in range(nbNodesX)]
78         coordsX=MC.DataArrayDouble.New()
79         coordsX.setValues(arrX,nbNodesX,1)
80
81         # For the Y dimension, we have to reverse the coordinates (the
82         # first pixel is at y=height and not at y=0).
83         stepY = 0.1
84         nbNodesY = sizeY+1
85         lengthY = sizeY*stepY
86         arrY=[float(lengthY - i * stepY) for i in range(nbNodesY)]
87         coordsY=MC.DataArrayDouble.New()
88         coordsY.setValues(arrY,nbNodesY,1)
89
90         cmesh.setCoords(coordsX,coordsY)
91         print("Imagem mesh dimension: %d"%cmesh.getSpaceDimension())
92
93         # WARN: In the current state of development of MEDLoader, only
94         # unstructured meshes are supported for writing function in med
95         # files. We just have to convert the cartesian mesh in an unstructured
96         # mesh before creating the field.
97         umesh=cmesh.buildUnstructured();
98         umesh.setName(cmesh.getName())
99
100         return umesh
101
102     def createField(self, fieldname, mesh, image):
103         """
104         Creating a scalar field on the mesh using image data
105         """
106         # Create the field using MEDCoupling
107         field = MC.MEDCouplingFieldDouble.New(MC.ON_CELLS,MC.ONE_TIME);
108         field.setName(fieldname);
109         field.setMesh(mesh);
110         # OPTIONAL: We set an arbitrary time step for test purpose
111         field.setIteration(0);
112         field.setOrder(0)
113
114         imagedata=list(image.getdata())
115         width,height=image.size
116         nbCells = width*height
117         dataArray=MC.DataArrayDouble.New();
118         nbComponents=1 # For a scalar field
119
120         dataArray.setValues(imagedata,nbCells,nbComponents)
121         field.setArray(dataArray);
122
123         return field
124
125 #
126 # ===================================================================
127 # use case functions
128 # ===================================================================
129 #
130
131 def getTestImagePath():
132     import os
133     FIELDS_ROOT_DIR=os.environ["FIELDS_ROOT_DIR"]
134     RESDIR=os.path.join(FIELDS_ROOT_DIR, "share", "salome", "resources", "fields", "medcalc_testfiles")
135     imgFileName="irm_test1.png"
136     imgFilePath=os.path.join(RESDIR,imgFileName)
137     return imgFilePath
138
139 def TEST_pil():
140     imgFilePath = getTestImagePath()
141     img=Image.open(imageFilepath)
142     imgbw=ImageOps.grayscale(img)
143
144
145 def TEST_image2med():
146     imgFilePath = getTestImagePath()
147     builder = FieldBuilder()
148     builder.image2med(imgFilePath,"image.med")
149
150 # ===================================================================
151 if __name__ == "__main__":
152     TEST_pil()
153     #TEST_image2med()