9 namespace {
union T {
unsigned i;
char c;};}
10 constexpr
bool is_little() {
return T({1}).c ==
'\1';}
15 if (e.
type!=t)
throw Error(
"Entry type error");
19 uint16_t Tiff::read16()
34 uint32_t Tiff::read32()
62 uint32_t Tiff::to32(DEntry
const & e)
64 if (e.type==4)
return e.data;
69 std::string Tiff::get_str(DEntry
const & e)
72 std::vector<char> b(e.count);
74 sp->read(b.data(),e.count);
75 if (b[e.count-1]!=
'\0')
warn <<
"String does not end with '\\0'";
76 return std::string(b.data(),e.count);
79 std::vector<uint16_t> Tiff::get16s(DEntry
const & e)
81 std::vector<uint16_t> r;
84 r.push_back(get16(e));
85 if (e.count==2) r.push_back(next16(e));
89 for (
unsigned i = 0; i<e.count; i++) r.push_back(read16());
94 std::vector<uint32_t> Tiff::get32s(DEntry
const & e)
96 std::vector<uint32_t> r;
98 if (e.count<=1) r.push_back(e.data);
101 for (
unsigned i = 0; i<e.count; i++) r.push_back(read32());
106 std::tuple<uint32_t,uint32_t> Tiff::get_ratio(DEntry
const & e)
110 return {read32(),read32()};
119 le = string(b) ==
"II";
121 auto check = read16();
122 debug <<
'[' << b <<
"]:" << check <<
'\n';
124 debug <<
"IFD at " << ifd <<
'\n';
131 debug <<
"# dentry = " << nde <<
'\n';
132 vector<DEntry> delist;
133 for (
unsigned i = 0; i < nde; i ++) {
134 auto e = read_dentry();
137 uint32_t ni = read32();
138 static map<Tag,function<void(DEntry&)> > ptag = {
139 {Tag_ImageWidth,[
this](
DEntry& e){image_width = to32(e);}},
140 {Tag_ImageLength,[
this](
DEntry& e){image_length = to32(e);}},
141 {Tag_BitsPerSample,[
this](
DEntry& e){bits_per_sample = get16s(e);}},
143 {Tag_PhotometricInterpretation,[
this](
DEntry& e){photometric = (
Photometric)get16(e);}},
144 {Tag_FillOrder,[
this](
DEntry& e){fill_order = get16(e);}},
145 {Tag_ImageDescription,[
this](
DEntry& e){image_description = get_str(e);}},
146 {Tag_StripOffsets,[
this](
DEntry& e){strip_offsets = get32s(e);}},
147 {Tag_Orientation,[
this](
DEntry& e){orientation = get16(e);}},
148 {Tag_SamplesPerPixel,[
this](
DEntry& e){samples_per_pixel = to32(e);}},
149 {Tag_RowsPerStrip,[
this](
DEntry& e){rows_per_strip = to32(e);}},
150 {Tag_StripByteCounts,[
this](
DEntry& e){strip_byte_counts = get32s(e);}},
151 {Tag_XResolution,[
this](
DEntry& e){xresolution = get_ratio(e);}},
152 {Tag_YResolution,[
this](
DEntry& e){yresolution = get_ratio(e);}},
153 {Tag_PlanarConfiguration,[
this](
DEntry& e){planar_configuration = get16(e);}},
154 {Tag_ResolutionUnit,[
this](
DEntry& e){resolution_unit = (
Unit)get16(e);}},
155 {Tag_Software,[
this](
DEntry& e){software = get_str(e);}},
156 {Tag_SampleFormat,[
this](
DEntry& e){
for (
auto i:get16s(e)) sample_formats.push_back((
SampleFormat)i);}},
157 {Tag_ImageID,[
this](
DEntry& e){image_id = get_str(e);}}
159 for (
auto e: delist) {
160 auto i = ptag.find((
Tag)e.
tag);
161 if (i!=ptag.end()) i->second(e);
162 else info <<
"unprocessed tag:" << e.
tag <<
'\n';
164 debug <<
" next IFD: " << ni <<
'\n';
170 if (samples_per_pixel!=1 || bits_per_sample[0]!=16) {
171 error(
"Unprocessed samples_per_pixel or bits_per_sample");
173 size_t isz = image_width*image_length*2;
175 std::vector<char> b(isz);
176 size_t ns = (image_length+rows_per_strip-1)/rows_per_strip;
177 if (ns!=strip_offsets.size())
error(
"mismatch number of strip_offsets");
179 for (
unsigned i = 0; i<ns; i++) {
180 size_t z = strip_byte_counts[i];
181 sp->seekg(strip_offsets[i]);
182 sp->read(b.data()+tsz, z);
185 if (tsz!=isz)
error(
"Image byte size mismatch");
186 if (efix)
for (
size_t i = 0; i<isz; i += 2) {
std::vector< char > read_image()
std::ostream & warn
stream for warning messages
std::ostream & info
stream for informative messages
SampleFormat
Sample formats.
Photometric
Photometric formats.
Tag
Directory entry ID tags.
void error(std::string const &m)
throw an Error with given message string
constexpr bool is_little()
is little endian
uint16_t type
entry data type
Compression
Compression methods.
std::ostream & debug
stream for debug messages
uint32_t parse_ifd(uint32_t i=0)
Parse image file directory (IFD)
Class for processing TIFF file.