15 #ifdef BA_TIFF_SUPPORT
27 ReadWriteTiff::ReadWriteTiff()
32 , m_samplesPerPixel(0)
37 ReadWriteTiff::~ReadWriteTiff()
42 void ReadWriteTiff::read(std::istream& input_stream)
44 m_tiff = TIFFStreamOpen(
"MemTIFF", &input_stream);
46 throw std::runtime_error(
"ReadWriteTiff::read() -> Can't open the file.");
53 Datafield* ReadWriteTiff::readDatafield(std::istream& input_stream)
56 return m_data->clone();
59 void ReadWriteTiff::writeDatafield(
const Datafield& data, std::ostream& output_stream)
61 m_data.reset(data.
clone());
62 if (m_data->rank() != 2)
63 throw std::runtime_error(
"ReadWriteTiff::write -> Error. "
64 "Only 2-dim arrays supported");
65 m_tiff = TIFFStreamOpen(
"MemTIFF", &output_stream);
66 m_width = m_data->axis(0).size();
67 m_height = m_data->axis(1).size();
73 void ReadWriteTiff::read_header()
78 if (!TIFFGetField(m_tiff, TIFFTAG_IMAGEWIDTH, &width)
79 || !TIFFGetField(m_tiff, TIFFTAG_IMAGELENGTH, &height)) {
80 throw std::runtime_error(
"ReadWriteTiff::read_header() -> Error. "
81 "Can't read width/height.");
84 m_width = (size_t)width;
85 m_height = (size_t)height;
87 uint16_t orientationTag(0);
88 TIFFGetField(m_tiff, TIFFTAG_ORIENTATION, &orientationTag);
93 if (!TIFFGetField(m_tiff, TIFFTAG_BITSPERSAMPLE, &m_bitsPerSample))
95 if (8 != m_bitsPerSample && 16 != m_bitsPerSample && 32 != m_bitsPerSample)
99 if (!TIFFGetField(m_tiff, TIFFTAG_SAMPLESPERPIXEL, &m_samplesPerPixel))
100 m_samplesPerPixel = 1;
101 if (m_samplesPerPixel != 1)
104 if (!TIFFGetField(m_tiff, TIFFTAG_SAMPLEFORMAT, &m_sampleFormat))
107 switch (m_sampleFormat) {
112 if (32 != m_bitsPerSample)
120 std::ostringstream message;
121 message <<
"ReadWriteTiff::read_header() -> Error. "
122 <<
"Can't read tiff image with following parameters:" << std::endl
123 <<
" TIFFTAG_BITSPERSAMPLE: " << m_bitsPerSample << std::endl
124 <<
" TIFFTAG_SAMPLESPERPIXEL: " << m_samplesPerPixel << std::endl
125 <<
" TIFFTAG_SAMPLEFORMAT: " << m_sampleFormat << std::endl;
126 throw std::runtime_error(message.str());
130 void ReadWriteTiff::read_data()
134 ASSERT(0 == m_bitsPerSample % 8);
135 uint16_t bytesPerSample = m_bitsPerSample / 8;
136 tmsize_t buf_size = TIFFScanlineSize(m_tiff);
137 tmsize_t expected_size = bytesPerSample * m_width;
138 if (buf_size != expected_size)
139 throw std::runtime_error(
"ReadWriteTiff::read_data() -> Error. Wrong scanline size.");
141 tdata_t buf = _TIFFmalloc(buf_size);
143 throw std::runtime_error(
"ReadWriteTiff::read_data() -> Error. Can't allocate buffer.");
145 create_output_data();
147 std::vector<int8_t> line_buf;
148 line_buf.resize(buf_size, 0);
150 std::vector<unsigned> axes_indices(2);
152 for (uint32_t row = 0; row < (uint32_t)m_height; row++) {
153 if (TIFFReadScanline(m_tiff, buf, row) < 0)
154 throw std::runtime_error(
"ReadWriteTiff::read_data() -> Error. Error in scanline.");
156 memcpy(&line_buf[0], buf, buf_size);
158 for (
unsigned col = 0; col < m_width; ++col) {
159 axes_indices[0] = col;
160 axes_indices[1] =
static_cast<unsigned>(m_height) - 1 - row;
161 size_t global_index = m_data->frame().toGlobalIndex(axes_indices);
163 void* incoming = &line_buf[col * bytesPerSample];
166 switch (m_sampleFormat) {
168 switch (m_bitsPerSample) {
170 sample = *
reinterpret_cast<uint8_t*
>(incoming);
173 sample = *
reinterpret_cast<uint16_t*
>(incoming);
176 sample = *
reinterpret_cast<uint32_t*
>(incoming);
181 switch (m_bitsPerSample) {
183 sample = *
reinterpret_cast<int8_t*
>(incoming);
186 sample = *
reinterpret_cast<int16_t*
>(incoming);
189 sample = *
reinterpret_cast<int32_t*
>(incoming);
194 sample = double(*
reinterpret_cast<float*
>(incoming));
197 throw std::runtime_error(
"ReadWriteTiff: unexpected sample format");
200 (*m_data)[global_index] = sample;
206 void ReadWriteTiff::write_header()
209 TIFFSetField(m_tiff, TIFFTAG_ARTIST,
"BornAgain.IOFactory");
211 TIFFSetField(m_tiff, TIFFTAG_IMAGEDESCRIPTION,
212 "Image converted from BornAgain intensity file.");
213 TIFFSetField(m_tiff, TIFFTAG_SOFTWARE,
"BornAgain");
215 const auto width =
static_cast<uint32_t
>(m_width);
216 const auto height =
static_cast<uint32_t
>(m_height);
217 TIFFSetField(m_tiff, TIFFTAG_IMAGEWIDTH, width);
218 TIFFSetField(m_tiff, TIFFTAG_IMAGELENGTH, height);
221 uint16_t bitPerSample = 32;
222 uint16_t samplesPerPixel = 1;
223 TIFFSetField(m_tiff, TIFFTAG_BITSPERSAMPLE, bitPerSample);
224 TIFFSetField(m_tiff, TIFFTAG_SAMPLESPERPIXEL, samplesPerPixel);
226 TIFFSetField(m_tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISWHITE);
229 void ReadWriteTiff::write_data()
231 using sample_t = int;
232 tmsize_t buf_size =
sizeof(sample_t) * m_width;
233 tdata_t buf = _TIFFmalloc(buf_size);
235 throw std::runtime_error(
"ReadWriteTiff::write_data() -> Error. Can't allocate buffer.");
237 std::vector<sample_t> line_buf;
238 line_buf.resize(m_width, 0);
239 std::vector<unsigned> axes_indices(2);
240 for (
unsigned row = 0; row < (uint32_t)m_height; row++) {
241 for (
unsigned col = 0; col < line_buf.size(); ++col) {
242 axes_indices[0] = col;
243 axes_indices[1] =
static_cast<unsigned>(m_height) - 1 - row;
244 size_t global_index = m_data->frame().toGlobalIndex(axes_indices);
245 line_buf[col] =
static_cast<sample_t
>((*m_data)[global_index]);
247 memcpy(buf, &line_buf[0], buf_size);
249 if (TIFFWriteScanline(m_tiff, buf, row) < 0)
250 throw std::runtime_error(
251 "ReadWriteTiff::write_data() -> Error. Error in TIFFWriteScanline.");
257 void ReadWriteTiff::close()
267 void ReadWriteTiff::create_output_data()
272 new FixedBinAxis(
"y", m_height, 0.0,
double(m_height))}));
Defines the macro ASSERT.
#define ASSERT(condition)
Defines class FixedBinAxis.
Defines and implements templated class Frame.
Defines class ReadWriteTiff.
Defines various stuff in namespace Utils.
Stores radiation power per bin.
Datafield * clone() const
Axis with fixed bin size.
std::string getCurrentDateAndTime()