SimpleITK  
RawImageReading/RawImageReading.py
1 #!/usr/bin/env python
2 # =========================================================================
3 #
4 # Copyright NumFOCUS
5 #
6 # Licensed under the Apache License, Version 2.0 (the "License");
7 # you may not use this file except in compliance with the License.
8 # You may obtain a copy of the License at
9 #
10 # http://www.apache.org/licenses/LICENSE-2.0.txt
11 #
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS,
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 # See the License for the specific language governing permissions and
16 # limitations under the License.
17 #
18 # =========================================================================
19 
20 import argparse
21 import os
22 import tempfile
23 
24 import SimpleITK as sitk
25 
26 
27 def read_raw(
28  binary_file_name,
29  image_size,
30  sitk_pixel_type,
31  image_spacing=None,
32  image_origin=None,
33  big_endian=False,
34 ):
35  """
36  Read a raw binary scalar image.
37 
38  Parameters
39  ----------
40  binary_file_name (str): Raw, binary image file content.
41  image_size (tuple like): Size of image (e.g. [2048,2048])
42  sitk_pixel_type (SimpleITK pixel type: Pixel type of data (e.g.
43  sitk.sitkUInt16).
44  image_spacing (tuple like): Optional image spacing, if none given assumed
45  to be [1]*dim.
46  image_origin (tuple like): Optional image origin, if none given assumed to
47  be [0]*dim.
48  big_endian (bool): Optional byte order indicator, if True big endian, else
49  little endian.
50 
51  Returns
52  -------
53  SimpleITK image or None if fails.
54  """
55 
56  pixel_dict = {
57  sitk.sitkUInt8: "MET_UCHAR",
58  sitk.sitkInt8: "MET_CHAR",
59  sitk.sitkUInt16: "MET_USHORT",
60  sitk.sitkInt16: "MET_SHORT",
61  sitk.sitkUInt32: "MET_UINT",
62  sitk.sitkInt32: "MET_INT",
63  sitk.sitkUInt64: "MET_ULONG_LONG",
64  sitk.sitkInt64: "MET_LONG_LONG",
65  sitk.sitkFloat32: "MET_FLOAT",
66  sitk.sitkFloat64: "MET_DOUBLE",
67  }
68  direction_cosine = [
69  "1 0 0 1",
70  "1 0 0 0 1 0 0 0 1",
71  "1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1",
72  ]
73  dim = len(image_size)
74  header = [
75  "ObjectType = Image\n".encode(),
76  (f"NDims = {dim}\n").encode(),
77  (
78  "DimSize = " + " ".join([str(v) for v in image_size]) + "\n"
79  ).encode(),
80  (
81  "ElementSpacing = "
82  + (
83  " ".join([str(v) for v in image_spacing])
84  if image_spacing
85  else " ".join(["1"] * dim)
86  )
87  + "\n"
88  ).encode(),
89  (
90  "Offset = "
91  + (
92  " ".join([str(v) for v in image_origin])
93  if image_origin
94  else " ".join(["0"] * dim) + "\n"
95  )
96  ).encode(),
97  ("TransformMatrix = " + direction_cosine[dim - 2] + "\n").encode(),
98  ("ElementType = " + pixel_dict[sitk_pixel_type] + "\n").encode(),
99  "BinaryData = True\n".encode(),
100  ("BinaryDataByteOrderMSB = " + str(big_endian) + "\n").encode(),
101  # ElementDataFile must be the last entry in the header
102  (
103  "ElementDataFile = " + os.path.abspath(binary_file_name) + "\n"
104  ).encode(),
105  ]
106  fp = tempfile.NamedTemporaryFile(suffix=".mhd", delete=False)
107 
108  print(header)
109 
110  # Not using the tempfile with a context manager and auto-delete
111  # because on windows we can't open the file a second time for ReadImage.
112  fp.writelines(header)
113  fp.close()
114  img = sitk.ReadImage(fp.name)
115  os.remove(fp.name)
116  return img
117 
118 
119 parser = argparse.ArgumentParser()
120 parser.add_argument("raw_file_name", help="path to raw binary image file")
121 parser.add_argument(
122  "out_file_name", help="output file name when image read as little endian"
123 )
124 parser.add_argument(
125  "big_endian",
126  type=lambda v: v.lower() in {"1", "true"},
127  help="'false' for little ending or 'true'for big " "endian",
128 )
129 parser.add_argument(
130  "sitk_pixel_type", help="SimpleITK pixel type (e.g. sitk.sitkUInt16)"
131 )
132 parser.add_argument("sz", nargs="+", help="image size, x,y,...", type=int)
133 args = parser.parse_args()
134 
135 string_to_pixelType = {
136  "sitkUInt8": sitk.sitkUInt8,
137  "sitkInt8": sitk.sitkInt8,
138  "sitkUInt16": sitk.sitkUInt16,
139  "sitkInt16": sitk.sitkInt16,
140  "sitkUInt32": sitk.sitkUInt32,
141  "sitkInt32": sitk.sitkInt32,
142  "sitkUInt64": sitk.sitkUInt64,
143  "sitkInt64": sitk.sitkInt64,
144  "sitkFloat32": sitk.sitkFloat32,
145  "sitkFloat64": sitk.sitkFloat64,
146 }
147 
148 # Read the image using both big and little endian
149 image = read_raw(
150  binary_file_name=args.raw_file_name,
151  image_size=args.sz,
152  sitk_pixel_type=string_to_pixelType[args.sitk_pixel_type],
153  big_endian=args.big_endian,
154 )
155 
156 sitk.WriteImage(image, args.out_file_name)
157 
158 if "SITK_NOSHOW" not in os.environ:
159  sitk.Show(image, "raw converted")
itk::simple::WriteImage
SITKIO_EXPORT void WriteImage(const Image &image, const std::vector< std::string > &fileNames, bool useCompression=false, int compressionLevel=-1)
WriteImage is a procedural interface to the ImageSeriesWriter. class which is convenient for many ima...
itk::simple::Show
void SITKIO_EXPORT Show(const Image &image, const std::string &title="", const bool debugOn=ProcessObject::GetGlobalDefaultDebug())
itk::simple::ReadImage
SITKIO_EXPORT Image ReadImage(const std::vector< std::string > &fileNames, PixelIDValueEnum outputPixelType=sitkUnknown, const std::string &imageIO="")
ReadImage is a procedural interface to the ImageSeriesReader class which is convenient for most image...