00001 #include "string.h"
00002 #include <sstream>
00003
00004 #include "TIFF.h"
00005 #include "../Debug.h"
00006
00007 namespace FCam {
00008
00009
00010
00011
00012
00013 TIFFFile::IfdEntry::IfdEntry(const TiffIfdEntry &entry, TIFFFile *parent):
00014 entry(entry), info(NULL), parent(parent), state(UNREAD), val()
00015 {
00016 info = tiffEntryLookup(entry.tag);
00017 }
00018
00019 TIFFFile::IfdEntry::IfdEntry(uint16_t tag, const TagValue &val, TIFFFile *parent):
00020 entry(), info(NULL), parent(parent), state(INVALID), val(val)
00021 {
00022 entry.tag = tag;
00023 entry.count = 0;
00024 entry.offset = 0;
00025 info = tiffEntryLookup(tag);
00026 if (info) entry.type = info->type;
00027 setValue(val);
00028 }
00029
00030 TIFFFile::IfdEntry::IfdEntry(uint16_t tag, TIFFFile *parent): entry(), info(NULL), parent(parent), state(INVALID), val() {
00031 entry.tag = tag;
00032 }
00033
00034 bool TIFFFile::IfdEntry::valid() const {
00035 return state != INVALID;
00036 }
00037
00038 uint16_t TIFFFile::IfdEntry::tag() const {
00039 return entry.tag;
00040 }
00041
00042 const char* TIFFFile::IfdEntry::name() const {
00043 if (info == NULL) return "UnknownTag";
00044 else return info->name;
00045 }
00046
00047 const TagValue& TIFFFile::IfdEntry::value() const {
00048 if (state == UNREAD) {
00049 val = parse();
00050 if (!val.valid()) state = INVALID;
00051 }
00052 return val;
00053 }
00054
00055 bool TIFFFile::IfdEntry::setValue(const TagValue &newVal) {
00056 if (info == NULL) {
00057 switch(newVal.type) {
00058 case TagValue::Null:
00059 warning(Event::FileSaveWarning, "IfdEntry: NULL value passed in for tag %d", tag() );
00060 state = INVALID;
00061 return false;
00062 break;
00063 case TagValue::Int:
00064 case TagValue::IntVector:
00065 entry.type = TIFF_SLONG;
00066 break;
00067 case TagValue::Float:
00068 case TagValue::FloatVector:
00069 entry.type = TIFF_FLOAT;
00070 break;
00071 case TagValue::Double:
00072 case TagValue::DoubleVector:
00073 entry.type = TIFF_DOUBLE;
00074 break;
00075 case TagValue::String:
00076 case TagValue::StringVector:
00077 entry.type = TIFF_ASCII;
00078 break;
00079 case TagValue::Time:
00080 case TagValue::TimeVector:
00081 warning(Event::FileSaveWarning, "IfdEntry: Can't store TagValue::Time values in TIFF tag %d", tag() );
00082 state = INVALID;
00083 val = TagValue();
00084 return false;
00085 break;
00086 }
00087 } else {
00088 bool typeMismatch = false;
00089 switch(newVal.type) {
00090 case TagValue::Null:
00091 warning(Event::FileSaveWarning, "IfdEntry: NULL value passed in for tag %d", tag() );
00092 state = INVALID;
00093 return false;
00094 break;
00095 case TagValue::Int:
00096 case TagValue::IntVector:
00097 if (entry.type != TIFF_BYTE &&
00098 entry.type != TIFF_SHORT &&
00099 entry.type != TIFF_LONG &&
00100 entry.type != TIFF_SBYTE &&
00101 entry.type != TIFF_SSHORT &&
00102 entry.type != TIFF_SLONG &&
00103 entry.type != TIFF_IFD) {
00104 typeMismatch= true;
00105 }
00106 break;
00107 case TagValue::Float:
00108 case TagValue::FloatVector:
00109 if (entry.type != TIFF_FLOAT &&
00110 entry.type != TIFF_DOUBLE) {
00111 typeMismatch= true;
00112 }
00113 break;
00114 case TagValue::Double:
00115 case TagValue::DoubleVector:
00116 if (entry.type != TIFF_DOUBLE &&
00117 entry.type != TIFF_FLOAT &&
00118 entry.type != TIFF_RATIONAL &&
00119 entry.type != TIFF_SRATIONAL) {
00120 typeMismatch= true;
00121 }
00122 break;
00123 case TagValue::String:
00124 case TagValue::StringVector:
00125 if (entry.type != TIFF_ASCII &&
00126 entry.type != TIFF_BYTE &&
00127 entry.type != TIFF_SBYTE) {
00128 typeMismatch= true;
00129 }
00130 break;
00131 case TagValue::Time:
00132 case TagValue::TimeVector:
00133 typeMismatch = true;
00134 break;
00135 }
00136 if (typeMismatch) {
00137 warning(Event::FileSaveWarning, "IfdEntry: Trying to set tag %d (%s) of type %d to incompatible TagValue type %d",
00138 tag(), name(), entry.type, newVal.type);
00139 state = INVALID;
00140 return false;
00141 }
00142 }
00143 val = newVal;
00144 state = WRITTEN;
00145 return true;
00146 }
00147
00148 bool TIFFFile::IfdEntry::writeDataBlock(FILE *fw) {
00149 const TagValue &v = value();
00150 if (state == INVALID) {
00151 error(Event::FileSaveError,
00152 "IfdEntry::writeDataBlock: Trying to write invalid tag %d (%s)",
00153 tag(), name());
00154 return false;
00155 }
00156
00157 unsigned int bytesPerElement=0;
00158 switch (entry.type) {
00159 case TIFF_BYTE: bytesPerElement = 1; break;
00160 case TIFF_ASCII: bytesPerElement = 1; break;
00161 case TIFF_SHORT: bytesPerElement = 2; break;
00162 case TIFF_LONG: bytesPerElement = 4; break;
00163 case TIFF_RATIONAL: bytesPerElement = 8; break;
00164 case TIFF_SBYTE: bytesPerElement = 1; break;
00165 case TIFF_UNDEFINED: bytesPerElement = 1; break;
00166 case TIFF_SSHORT: bytesPerElement = 2; break;
00167 case TIFF_SLONG: bytesPerElement = 4; break;
00168 case TIFF_SRATIONAL: bytesPerElement = 8; break;
00169 case TIFF_FLOAT: bytesPerElement = 4; break;
00170 case TIFF_DOUBLE: bytesPerElement = 8; break;
00171 case TIFF_IFD: bytesPerElement = 4; break;
00172 }
00173 unsigned int elements = 0;
00174 switch (v.type) {
00175 case TagValue::Int:
00176 case TagValue::Float:
00177 case TagValue::Double:
00178 elements = 1;
00179 break;
00180 case TagValue::IntVector: {
00181 std::vector<int> &vi = v;
00182 elements = vi.size();
00183 break;
00184 }
00185 case TagValue::FloatVector: {
00186 std::vector<float> &vf = v;
00187 elements = vf.size();
00188 break;
00189 }
00190 case TagValue::DoubleVector: {
00191 std::vector<double> &vd = v;
00192 elements = vd.size();
00193 break;
00194 }
00195 case TagValue::String: {
00196 std::string &vs = v;
00197 if (entry.type == TIFF_ASCII) {
00198 elements = vs.size() + 1;
00199 } else {
00200 elements = vs.size();
00201 }
00202 break;
00203 }
00204 case TagValue::StringVector: {
00205 std::vector<std::string> &strs = v;
00206 for (size_t i=0; i < strs.size(); i++) {
00207 elements += strs[i].size()+1;
00208 }
00209 break;
00210 }
00211 default:
00212 error(Event::FileSaveError, "IfdEntry::writeDataBlock: Unexpected TagValue type.");
00213 return false;
00214 break;
00215 }
00216
00217 entry.count = elements;
00218
00219 uint32_t dataBytes = bytesPerElement * elements;
00220
00221 if (dataBytes <= 4) {
00222
00223 switch(entry.type) {
00224 case TIFF_BYTE: {
00225 uint8_t *off = (uint8_t *)&entry.offset;
00226 if (v.type == TagValue::Int) {
00227 uint8_t byte = (int)v;
00228 *off = byte;
00229 } else if (v.type == TagValue::IntVector) {
00230 std::vector<int> &bytes = v;
00231 for (size_t i=0; i < elements; i++) {
00232 *off++ = bytes[i];
00233 }
00234 } else {
00235 std::string &bytes = v;
00236 for (size_t i=0; i < elements; i++) {
00237 *off++ = bytes[i];
00238 }
00239 }
00240 break;
00241 }
00242 case TIFF_ASCII: {
00243 uint8_t *off = (uint8_t *)&entry.offset;
00244 if (v.type == TagValue::String) {
00245 std::string &ascii = v;
00246 for (size_t i=0; i < ascii.size(); i++) {
00247 *off++ = ascii[i];
00248 }
00249 *off = 0;
00250 } else {
00251 std::vector<std::string> &asciis = v;
00252 for (size_t i=0; i < asciis.size(); i++) {
00253 for (size_t j=0; j < asciis[i].size(); j++) {
00254 *off++ = asciis[i][j];
00255 }
00256 *off++ = 0;
00257 }
00258 }
00259 break;
00260 }
00261 case TIFF_SHORT: {
00262 uint16_t *off = (uint16_t *)(void *)&entry.offset;
00263 if (v.type == TagValue::Int) {
00264 uint16_t vs = (int)v;
00265 *off = vs;
00266 } else {
00267 std::vector<int> &shorts = v;
00268 for (size_t i=0; i < elements; i++) {
00269 *off++ = shorts[i];
00270 }
00271 }
00272 break;
00273 }
00274 case TIFF_IFD:
00275 case TIFF_LONG: {
00276 if (v.type == TagValue::Int) {
00277 uint32_t vs = (int)v;
00278 entry.offset = vs;
00279 } else {
00280 std::vector<int> &vi = v;
00281 entry.offset = (uint32_t)vi[0];
00282 }
00283 break;
00284 }
00285 case TIFF_SBYTE: {
00286 int8_t *off = (int8_t *)&entry.offset;
00287 if (v.type == TagValue::Int) {
00288 int8_t byte = (int)v;
00289 *off = byte;
00290 } else if (v.type == TagValue::IntVector) {
00291 std::vector<int> &bytes = v;
00292 for (size_t i=0; i < elements; i++) {
00293 *off++ = bytes[i];
00294 }
00295 } else {
00296 std::string &bytes = v;
00297 for (size_t i=0; i < elements; i++) {
00298 *off++ = bytes[i];
00299 }
00300 }
00301 break;
00302 }
00303 case TIFF_UNDEFINED: {
00304 uint8_t *off = (uint8_t *)&entry.offset;
00305 std::string &bytes = v;
00306 for (size_t i=0; i < elements; i++) {
00307 *off++ = bytes[i];
00308 }
00309 break;
00310 }
00311 case TIFF_SSHORT: {
00312 int16_t *off = (int16_t *)(void *)&entry.offset;
00313 if (v.type == TagValue::Int) {
00314 int16_t vs = (int)v;
00315 *off = vs;
00316 } else {
00317 std::vector<int> &shorts = v;
00318 for (size_t i=0; i < elements; i++) {
00319 *off++ = shorts[i];
00320 }
00321 }
00322 break;
00323 }
00324 case TIFF_SLONG: {
00325 if (v.type == TagValue::Int) {
00326 int32_t vs = (int)v;
00327 entry.offset = vs;
00328 } else {
00329 std::vector<int> &vi = v;
00330 entry.offset = vi[0];
00331 }
00332 break;
00333 }
00334 case TIFF_FLOAT: {
00335 float *off = (float *)(void *)&entry.offset;
00336 if (v.type == TagValue::Float) {
00337 float vf = v;
00338 *off = vf;
00339 } else {
00340 std::vector<float> &vf = v;
00341 *off = vf[0];
00342 }
00343 break;
00344 }
00345 }
00346 } else {
00347
00348
00349
00350 #if FCAM_DEBUG_LEVEL >= 6
00351 dprintf(6, "TIFFile::IfdEntry::writeDataBlock: Tag %d (%s) data: %s\n", entry.tag, name(), v.toString().substr(0,200).c_str());
00352 #else
00353 dprintf(5, "TIFFile::IfdEntry::writeDataBlock: Writing tag %d (%s) data block.\n", entry.tag, name());
00354 #endif
00355
00356
00357
00358 entry.offset = ftell(fw);
00359 size_t written = 0;
00360 switch(entry.type) {
00361 case TIFF_BYTE: {
00362 if (v.type == TagValue::IntVector) {
00363 std::vector<int> &vi = v;
00364 std::vector<uint8_t> bytes(vi.begin(), vi.end());
00365 written = fwrite(&bytes[0], sizeof(uint8_t), elements, fw);
00366 } else {
00367 std::string &vs = v;
00368 written = fwrite(vs.data(), sizeof(uint8_t), elements, fw);
00369 }
00370 break;
00371 }
00372 case TIFF_ASCII: {
00373 if (v.type == TagValue::String) {
00374 std::string &ascii = v;
00375 written = fwrite(ascii.c_str(), sizeof(char), elements, fw);
00376 } else {
00377 std::vector<std::string> &asciis = v;
00378 for (size_t i=0; i < asciis.size(); i++) {
00379 written += fwrite(asciis[i].c_str(), sizeof(char), asciis[i].size()+1, fw);
00380 }
00381 }
00382 break;
00383 }
00384 case TIFF_SHORT: {
00385 std::vector<int> &vi = v;
00386 std::vector<uint16_t> shorts(vi.begin(), vi.end());
00387 written = fwrite(&shorts[0], sizeof(uint16_t), shorts.size(), fw);
00388 break;
00389 }
00390 case TIFF_IFD:
00391 case TIFF_LONG: {
00392 std::vector<int> &vi = v;
00393 written = fwrite(&vi[0], sizeof(uint32_t), vi.size(), fw);
00394 break;
00395 }
00396 case TIFF_SRATIONAL:
00397 case TIFF_RATIONAL: {
00398 if (v.type == TagValue::Double) {
00399 double vd = v;
00400
00401 uint32_t num = vd * (2 << 20);
00402 uint32_t den = 2 << 20;;
00403 written = fwrite(&num, sizeof(uint32_t), 1, fw);
00404 written += fwrite(&den, sizeof(uint32_t), 1, fw);
00405 written /= 2;
00406 } else {
00407 std::vector<double> &vd = v;
00408 written = 0;
00409 for (size_t i=0; i < vd.size(); i++) {
00410 uint32_t num = vd[i] * (2 << 20);
00411 uint32_t den = 2 << 20;
00412 written += fwrite(&num, sizeof(uint32_t), 1, fw);
00413 written += fwrite(&den, sizeof(uint32_t), 1, fw);
00414 }
00415 written /= 2;
00416 }
00417 break;
00418 }
00419 case TIFF_SBYTE: {
00420 if (v.type == TagValue::IntVector) {
00421 std::vector<int> &vi = v;
00422 std::vector<int8_t> bytes(vi.begin(), vi.end());
00423 written = fwrite(&bytes[0], sizeof(int8_t), elements, fw);
00424 } else {
00425 std::string &vs = v;
00426 written = fwrite(vs.data(), sizeof(int8_t), elements, fw);
00427 }
00428 break;
00429 }
00430 case TIFF_UNDEFINED: {
00431 std::string &vs = v;
00432 written = fwrite(vs.data(), sizeof(int8_t), elements, fw);
00433 break;
00434 }
00435 case TIFF_SSHORT: {
00436 std::vector<int> &vi = v;
00437 std::vector<int16_t> shorts(vi.begin(), vi.end());
00438 written = fwrite(&shorts[0], sizeof(int16_t), elements, fw);
00439 break;
00440 }
00441 case TIFF_SLONG: {
00442 std::vector<int> &vi = v;
00443 written = fwrite(&vi[0], sizeof(uint32_t), elements, fw);
00444 break;
00445 }
00446 case TIFF_FLOAT: {
00447 std::vector<float> &vf = v;
00448 written = fwrite(&vf[0], sizeof(float), elements, fw);
00449 break;
00450 }
00451 case TIFF_DOUBLE: {
00452 if (elements == 1) {
00453 double vd = v;
00454 written = fwrite(&vd, sizeof(double), elements, fw);
00455 } else {
00456 std::vector<double> &vd = v;
00457 written = fwrite(&vd[0], sizeof(double), elements, fw);
00458 }
00459 break;
00460 }
00461 }
00462 if (written != elements) {
00463 error(Event::FileSaveError, "TIFFFile::IfdEntry::writeDataBlock: Can't write data to file (tried to write %d, only wrote %d)", elements, written);
00464 return false;
00465 }
00466 }
00467
00468 return true;
00469 }
00470
00471 bool TIFFFile::IfdEntry::write(FILE *fw) {
00472 dprintf(5, "TIFFile::IfdEntry::write: Writing tag entry %d (%s): %d %d %d\n", tag(), name(), entry.type, entry.count, entry.offset);
00473 int count;
00474 count = fwrite(&entry.tag, sizeof(entry.tag), 1, fw);
00475 if (count == 1) fwrite(&entry.type, sizeof(entry.type), 1, fw);
00476 if (count == 1) fwrite(&entry.count, sizeof(entry.count), 1, fw);
00477 if (count == 1) fwrite(&entry.offset, sizeof(entry.offset), 1, fw);
00478
00479 if (count != 1) {
00480 error(Event::FileSaveError, "TIFFile::IfdEntry::write: Can't write IFD entry to file.");
00481 return false;
00482 }
00483 return true;
00484
00485 }
00486
00487 bool TIFFFile::IfdEntry::operator<(const IfdEntry &other) const {
00488 return tag() < other.tag();
00489 }
00490
00491 TagValue TIFFFile::IfdEntry::parse() const {
00492 TagValue tag;
00493
00494 if (info != NULL) {
00495
00496 bool typeMismatch=false;
00497 switch(info->type) {
00498 case TIFF_BYTE:
00499 case TIFF_SHORT:
00500 case TIFF_LONG:
00501
00502 if (entry.type != TIFF_BYTE &&
00503 entry.type != TIFF_SHORT &&
00504 entry.type != TIFF_LONG)
00505 typeMismatch = true;
00506 break;
00507 case TIFF_SBYTE:
00508 case TIFF_SSHORT:
00509 case TIFF_SLONG:
00510
00511 if (entry.type != TIFF_SBYTE &&
00512 entry.type != TIFF_SSHORT &&
00513 entry.type != TIFF_SLONG)
00514 typeMismatch = true;
00515 break;
00516 case TIFF_ASCII:
00517 case TIFF_RATIONAL:
00518 case TIFF_UNDEFINED:
00519 case TIFF_SRATIONAL:
00520 case TIFF_FLOAT:
00521 case TIFF_DOUBLE:
00522
00523 if (entry.type != info->type) typeMismatch = true;
00524 break;
00525 case TIFF_IFD:
00526
00527 if (entry.type != TIFF_LONG &&
00528 entry.type != TIFF_IFD) typeMismatch = true;
00529 break;
00530 }
00531 if (typeMismatch) {
00532 warning(Event::FileLoadWarning,
00533 "In %s, type mismatch reading TIFF tag %d (%s), expected type %d, got %d\n",
00534 parent->filename.c_str(), entry.tag, info->name, info->type, entry.type);
00535 return tag;
00536 }
00537 }
00538
00539 unsigned int bytesPerElement=0;
00540 switch (entry.type) {
00541 case TIFF_BYTE: bytesPerElement = 1; break;
00542 case TIFF_ASCII: bytesPerElement = 1; break;
00543 case TIFF_SHORT: bytesPerElement = 2; break;
00544 case TIFF_LONG: bytesPerElement = 4; break;
00545 case TIFF_RATIONAL: bytesPerElement = 8; break;
00546 case TIFF_SBYTE: bytesPerElement = 1; break;
00547 case TIFF_UNDEFINED: bytesPerElement = 1; break;
00548 case TIFF_SSHORT: bytesPerElement = 2; break;
00549 case TIFF_SLONG: bytesPerElement = 4; break;
00550 case TIFF_SRATIONAL: bytesPerElement = 8; break;
00551 case TIFF_FLOAT: bytesPerElement = 4; break;
00552 case TIFF_DOUBLE: bytesPerElement = 8; break;
00553 case TIFF_IFD: bytesPerElement = 4; break;
00554 }
00555 unsigned int totalBytes = entry.count*bytesPerElement;
00556 std::vector<uint8_t> data(totalBytes);
00557
00558
00559 if (entry.count > 4/bytesPerElement) {
00560
00561 int adjOffset = parent->convLong(&entry.offset);
00562 bool success = parent->readByteArray(adjOffset, totalBytes, &data[0]);
00563 if (!success) {
00564 warning(Event::FileLoadWarning,
00565 "In %s, unable to read TIFF tag %d (%s) data at offset 0x%x\n",
00566 parent->filename.c_str(), entry.tag, name(), entry.offset);
00567 return tag;
00568 }
00569 } else {
00570 uint8_t *ptr = (uint8_t*)&entry.offset;
00571 for (size_t i=0; i < data.size(); i++) {
00572 data[i] = *(ptr++);
00573 }
00574 }
00575
00576 switch (entry.type) {
00577 case TIFF_BYTE:
00578 case TIFF_SBYTE:
00579 case TIFF_UNDEFINED:
00580 tag = std::string(data.begin(), data.end());
00581 break;
00582 case TIFF_ASCII: {
00583
00584 std::vector<std::string> strings;
00585 std::vector<uint8_t>::iterator start = data.begin();
00586 for (std::vector<uint8_t>::iterator it=data.begin(); it < data.end(); it++) {
00587 if (*it == 0) {
00588 strings.push_back(std::string(start, it));
00589 start = it + 1;
00590 }
00591 }
00592 if (strings.size() > 1) {
00593 tag = strings;
00594 } else {
00595 tag = strings[0];
00596 }
00597 break;
00598 }
00599 case TIFF_SHORT:
00600 if (entry.count > 1) {
00601 std::vector<int> vals(entry.count);
00602 uint8_t *ptr = &data[0];
00603 for (size_t i=0; i < entry.count; i++) {
00604 vals[i] = parent->convShort(ptr);
00605 ptr+=bytesPerElement;
00606 }
00607 tag = vals;
00608 } else {
00609 tag = parent->convShort(&data[0]);
00610 }
00611 break;
00612 case TIFF_IFD:
00613 case TIFF_LONG:
00614
00615 if (entry.count > 1) {
00616 std::vector<int> vals(entry.count);
00617 uint8_t *ptr = &data[0];
00618 for (size_t i=0; i < entry.count; i++) {
00619 vals[i] = (int)parent->convLong(ptr);
00620 ptr+=bytesPerElement;
00621 }
00622 tag = vals;
00623 } else {
00624 tag = (int)parent->convLong(&data[0]);
00625 }
00626 break;
00627 case TIFF_RATIONAL:
00628 if (entry.count > 1) {
00629 std::vector<double> vals(entry.count);
00630 uint8_t *ptr = &data[0];
00631 for (size_t i=0; i < entry.count; i++) {
00632 TIFFRational r = parent->convRational(ptr);
00633
00634 vals[i] = ((double)r.numerator)/((double)r.denominator);
00635 ptr+=bytesPerElement;
00636 }
00637 tag = vals;
00638 } else {
00639 TIFFRational r = parent->convRational(&data[0]);
00640 tag = ((double)r.numerator)/((double)r.denominator);
00641 }
00642 break;
00643 case TIFF_SSHORT:
00644 if (entry.count > 1) {
00645 std::vector<int> vals(entry.count);
00646 uint8_t *ptr = &data[0];
00647 for (size_t i=0; i < entry.count; i++) {
00648 uint16_t val = parent->convShort(ptr);
00649 vals[i] = *reinterpret_cast<int16_t *>(&val);
00650 ptr+=bytesPerElement;
00651 }
00652 tag = vals;
00653 } else {
00654 uint16_t val = parent->convShort(&data[0]);
00655 tag = *reinterpret_cast<int16_t *>(&val);
00656 }
00657 break;
00658
00659 case TIFF_SLONG:
00660 if (entry.count > 1) {
00661 std::vector<int> vals(entry.count);
00662 uint8_t *ptr = &data[0];
00663 for (size_t i=0; i < entry.count; i++) {
00664 uint32_t val = parent->convLong(ptr);
00665 vals[i] = *reinterpret_cast<int32_t *>(&val);
00666 ptr+=bytesPerElement;
00667 }
00668 tag = vals;
00669 } else {
00670 uint32_t val = parent->convLong(&data[0]);
00671 tag = *reinterpret_cast<int32_t *>(&val);
00672 }
00673 break;
00674 case TIFF_SRATIONAL:
00675 if (entry.count > 1) {
00676 std::vector<double> vals(entry.count);
00677 uint8_t *ptr = &data[0];
00678 for (size_t i=0; i < entry.count; i++) {
00679 TIFFRational r = parent->convRational(ptr);
00680
00681 vals[i] = (static_cast<double>(*reinterpret_cast<int32_t *>(&r.numerator)))
00682 /(static_cast<double>(*reinterpret_cast<int32_t *>(&r.denominator)));
00683 ptr+=bytesPerElement;
00684 }
00685 tag = vals;
00686 } else {
00687 TIFFRational r = parent->convRational(&data[0]);
00688 tag = (static_cast<double>(*reinterpret_cast<int32_t *>(&r.numerator)))
00689 /(static_cast<double>(*reinterpret_cast<int32_t *>(&r.denominator)));
00690 }
00691 break;
00692 case TIFF_FLOAT:
00693 if (entry.count > 1) {
00694 std::vector<float> vals(entry.count);
00695 uint8_t *ptr = &data[0];
00696 for (size_t i=0; i < entry.count; i++) {
00697 vals[i] = parent->convFloat(ptr);
00698 ptr+=bytesPerElement;
00699 }
00700 tag = vals;
00701 } else {
00702 tag = parent->convFloat(&data[0]);
00703 }
00704 break;
00705 case TIFF_DOUBLE:
00706 if (entry.count > 1) {
00707 std::vector<double> vals(entry.count);
00708 uint8_t *ptr = &data[0];
00709 for (size_t i=0; i < entry.count; i++) {
00710 vals[i] = parent->convDouble(ptr);
00711 ptr+=bytesPerElement;
00712 }
00713 tag = vals;
00714 } else {
00715 tag = parent->convDouble(&data[0]);
00716 }
00717 break;
00718 };
00719
00720 state = READ;
00721
00722 return tag;
00723 }
00724
00725
00726
00727
00728
00729 TIFFFile::Ifd::Ifd(TIFFFile *parent): parent(parent), imgState(UNREAD) {
00730 }
00731
00732 TIFFFile::Ifd::~Ifd() {
00733 eraseSubIfds();
00734 }
00735
00736 const TIFFFile::IfdEntry* TIFFFile::Ifd::find(uint16_t tag) const {
00737 entryMap::const_iterator match;
00738 match=entries.find(tag);
00739 if (match == entries.end()) return NULL;
00740 else return &(match->second);
00741 }
00742
00743 TIFFFile::IfdEntry* TIFFFile::Ifd::find(uint16_t tag) {
00744 entryMap::iterator match;
00745 match=entries.find(tag);
00746 if (match == entries.end()) return NULL;
00747 else return &(match->second);
00748 }
00749
00750 bool TIFFFile::Ifd::add(const TiffIfdEntry &rawEntry) {
00751 IfdEntry entry(rawEntry, parent);
00752
00753 entries.insert(entries.end(), entryMap::value_type(rawEntry.tag, entry));
00754 return true;
00755 }
00756
00757 bool TIFFFile::Ifd::add(uint16_t tag, const TagValue &val) {
00758 IfdEntry entry(tag, val, parent);
00759 if (!entry.valid()) return false;
00760 IfdEntry *existingEntry = find(tag);
00761 if (existingEntry) existingEntry->setValue(val);
00762 else {
00763 entries.insert(entryMap::value_type(tag, entry));
00764 }
00765 return true;
00766 }
00767
00768 bool TIFFFile::Ifd::add(const std::string &tagName, const TagValue &val) {
00769 const TiffEntryInfo *info = tiffEntryLookup(tagName);
00770 if (info) {
00771 return add(info->tag, val);
00772 }
00773 return false;
00774 }
00775
00776 TIFFFile::Ifd* TIFFFile::Ifd::addSubIfd() {
00777 Ifd *ifd = new Ifd(parent);
00778 _subIfds.push_back(ifd);
00779 return ifd;
00780 }
00781
00782 void TIFFFile::Ifd::eraseSubIfds() {
00783 for (size_t i=0; i < _subIfds.size(); i++) {
00784 delete _subIfds[i];
00785 }
00786 _subIfds.clear();
00787 }
00788
00789 const std::vector<TIFFFile::Ifd *>& TIFFFile::Ifd::subIfds() {
00790 return _subIfds;
00791 }
00792
00793 TIFFFile::Ifd* TIFFFile::Ifd::subIfds(int index) {
00794 return _subIfds[index];
00795 }
00796
00797 Image TIFFFile::Ifd::getImage() {
00798 if (imgState == NONE || imgState == CACHED) return imgCache;
00799
00800 const IfdEntry *entry;
00801
00802 const char *file = parent->filename.c_str();
00803
00804 entry = find(TIFF_TAG_PhotometricInterpretation);
00805 if (!entry) {
00806 imgState = NONE;
00807 return imgCache;
00808 }
00809 int photometricInterpretation = entry->value();
00810
00811 #define fatalError(...) \
00812 do { \
00813 warning(Event::FileLoadError, __VA_ARGS__); \
00814 imgState = NONE; \
00815 return imgCache; \
00816 } while(0);
00817
00818 ImageFormat fmt = UNKNOWN;
00819 switch (photometricInterpretation) {
00820 case TIFF_PhotometricInterpretation_WhiteIsZero:
00821 case TIFF_PhotometricInterpretation_BlackIsZero:
00822 case TIFF_PhotometricInterpretation_PaletteRGB:
00823 case TIFF_PhotometricInterpretation_TransparencyMask:
00824 case TIFF_PhotometricInterpretation_CMYK:
00825 case TIFF_PhotometricInterpretation_CIELAB:
00826 case TIFF_PhotometricInterpretation_ICCLAB:
00827 case TIFF_PhotometricInterpretation_ITULAB:
00828 case TIFF_PhotometricInterpretation_YCbCr:
00829
00830 fatalError("Ifd::getImage(): %s: Unsupported pixel format (PhotometricInterpretation) %d.",
00831 file,
00832 photometricInterpretation);
00833 break;
00834 case TIFF_PhotometricInterpretation_RGB:
00835 fmt = RGB24;
00836 break;
00837 case TIFF_PhotometricInterpretation_LinearRaw:
00838 fatalError("Ifd::getImage(): %s: Linear RAW is not supported.",
00839 file);
00840 break;
00841 case TIFF_PhotometricInterpretation_CFA:
00842 fmt = RAW;
00843 break;
00844
00845 }
00846
00847 int compression = TIFF_Compression_DEFAULT;
00848 entry = find(TIFF_TAG_Compression);
00849 if (entry) compression = entry->value();
00850
00851 switch (compression) {
00852 case TIFF_Compression_Uncompressed:
00853
00854 break;
00855 default:
00856 fatalError("Ifd::getImage(): %s: Unsupported compression type %d.",
00857 file,
00858 compression);
00859 break;
00860 }
00861
00862
00863 int samplesPerPixel = TIFF_SamplesPerPixel_DEFAULT;
00864 entry = find(TIFF_TAG_SamplesPerPixel);
00865 if (entry) samplesPerPixel = entry->value();
00866 switch (fmt) {
00867 case RAW:
00868 if (samplesPerPixel != 1) {
00869 fatalError("Ifd::getImage(): %s: RAW images cannot have more than 1 sample per pixel.",
00870 file);
00871 }
00872 break;
00873 case RGB24:
00874 if (samplesPerPixel != 3) {
00875 fatalError("Ifd::getImage(): %s: RGB24 images must have 3 samples per pixel", file);
00876 }
00877 break;
00878 default:
00879 fatalError("Ifd::getImage(): %s: Unexpected branch in the road", file);
00880 break;
00881 }
00882
00883 entry = find(TIFF_TAG_BitsPerSample);
00884 if (!entry) fatalError("Ifd::getImage(): %s: No BitsPerSample entry found.", file);
00885
00886 switch (fmt) {
00887 case RAW: {
00888 int bitsPerSample = entry->value();
00889 if (bitsPerSample != 16) fatalError("Ifd::getImage(): %s: Only 16-bpp RAW images supported.", file);
00890 break;
00891 }
00892 case RGB24: {
00893 std::vector<int> bitsPerSample = entry->value();
00894 if (bitsPerSample[0] != 8 ||
00895 bitsPerSample[1] != 8||
00896 bitsPerSample[2] != 8) fatalError("Ifd::getImage(): %s: Only 24-bpp RGB images supported.", file);
00897 break;
00898 }
00899 default:
00900 fatalError("Ifd::getImage(): %s: Unexpected branch in the road", file);
00901 break;
00902 }
00903
00904 entry = find(TIFF_TAG_Orientation);
00905 if (!entry) fatalError("Ifd::getImage(): %s: No orientation entry found, required for RAW.", file);
00906 int orientation = entry->value();
00907
00908 if (orientation != 1) fatalError("Ifd::getImage(): %s: Unsupported orientation value %d", file, orientation);
00909
00910
00911 entry = find(TIFF_TAG_ImageWidth);
00912 if (!entry) fatalError("Ifd::getImage(): %s: No ImageWidth entry found.", file);
00913 int imageWidth = entry->value();
00914
00915 entry = find(TIFF_TAG_ImageLength);
00916 if (!entry) fatalError("Ifd::getImage(): %s: No ImageLength entry found.", file);
00917 int imageLength = entry->value();
00918
00919 dprintf(4,"Ifd::getImage(): %s: Image size is %d x %d\n", file, imageWidth, imageLength);
00920
00921
00922 entry = find(TIFF_TAG_RowsPerStrip);
00923 int rowsPerStrip = TIFF_RowsPerStrip_DEFAULT;
00924 uint32_t stripsPerImage = 1;
00925 if (entry) {
00926 rowsPerStrip = entry->value();
00927 stripsPerImage = imageLength / rowsPerStrip;
00928 if (imageLength % rowsPerStrip != 0) stripsPerImage++;
00929 }
00930
00931 entry = find(TIFF_TAG_StripOffsets);
00932 if (!entry) fatalError("Ifd::getImage(): %s: No image strip data found, and tiled data is not supported.", file);
00933 std::vector<int> stripOffsets = entry->value();
00934 if (stripOffsets.size() != stripsPerImage)
00935 fatalError("Ifd::getImage(): %s: Malformed IFD - conflicting values on number of image strips.", file);
00936
00937 dprintf(5, "Ifd::getImage(): %s: Image data in %d strips of %d rows each.\n", file, stripsPerImage, rowsPerStrip);
00938
00939
00940
00941 Image img(imageWidth, imageLength, fmt);
00942
00943 uint32_t bytesPerStrip = rowsPerStrip * imageWidth * img.bytesPerPixel();
00944 uint32_t bytesLeft = imageLength * imageWidth * img.bytesPerPixel();
00945 for (uint32_t strip=0; strip < stripsPerImage; strip++) {
00946 uint32_t bytesToRead = std::min(bytesLeft, bytesPerStrip);
00947 bool success = parent->readByteArray(stripOffsets[strip], bytesToRead, img(0,rowsPerStrip*strip) );
00948 if (!success) {
00949 fatalError("Ifd::getImage(): %s: Cannot read in all image data.\n", file);
00950 }
00951 bytesLeft -= bytesToRead;
00952 }
00953
00954 #undef fatalError
00955
00956 imgCache = img;
00957 imgState = CACHED;
00958 return imgCache;
00959 }
00960
00961 bool TIFFFile::Ifd::setImage(Image newImg) {
00962 if (newImg.type() != RAW &&
00963 newImg.type() != RGB24) {
00964 error(Event::FileSaveError, "Ifd::setImage(): Can only save RAW or RGB24 images");
00965 return false;
00966 }
00967 imgCache = newImg;
00968 imgState = CACHED;
00969 return true;
00970 }
00971
00972 bool TIFFFile::Ifd::write(FILE *fw, uint32_t nextIfdOffset, uint32_t *offset) {
00973 bool success;
00974
00975 if (_subIfds.size() > 0) {
00976 std::vector<int> subIfdOffsets;
00977
00978 for (size_t i=0; i < _subIfds.size(); i++ ) {
00979 uint32_t subIfdOffset;
00980 dprintf(4, "TIFFile::Ifd::write: Writing subIFD %d\n", i);
00981 success = _subIfds[i]->write(fw, 0, &subIfdOffset);
00982 if (!success) return false;
00983 subIfdOffsets.push_back(subIfdOffset);
00984 }
00985
00986 IfdEntry *subIfdEntry = find(TIFF_TAG_SubIFDs);
00987 if (subIfdEntry != NULL) {
00988 success = subIfdEntry->setValue(TagValue(subIfdOffsets));
00989 } else {
00990 success = add(TIFF_TAG_SubIFDs, TagValue(subIfdOffsets));
00991 }
00992 if (!success) return false;
00993 }
00994
00995 success = writeImage(fw);
00996 if (!success) return false;
00997
00998
00999 dprintf(5, "TIFFile::Ifd::write: Writing Ifd entry data blocks.\n");
01000
01001 for (entryMap::iterator it=entries.begin(); it != entries.end(); it++) {
01002 success = it->second.writeDataBlock(fw);
01003 if (!success) return false;
01004 }
01005
01006
01007 *offset = ftell(fw);
01008
01009 int count;
01010 uint16_t entryCount = entries.size();
01011 count = fwrite(&entryCount, sizeof(uint16_t), 1, fw);
01012 if (count != 1) return false;
01013
01014 dprintf(5, "TIFFile::Ifd::write: Writing IFD entries\n");
01015 for (entryMap::iterator it=entries.begin(); it != entries.end(); it++) {
01016 success = it->second.write(fw);
01017 if (!success) return false;
01018 }
01019 count = fwrite(&nextIfdOffset, sizeof(uint32_t), 1, fw);
01020 if (count != 1) return false;
01021
01022 dprintf(5, "TIFFile::Ifd::write: IFD written\n");
01023 return true;
01024 }
01025
01026 bool TIFFFile::Ifd::writeImage(FILE *fw) {
01027 Image img = getImage();
01028 if (imgState == NONE) return true;
01029 dprintf(5, "TIFFile::Ifd::writeImage: Beginning image write\n");
01030 if (!img.valid()) {
01031 error(Event::FileSaveError, "TIFFFile::Ifd::writeImage: Invalid image");
01032 return false;
01033 }
01034
01035 int photometricInterpretation = 0;
01036 int samplesPerPixel = 0;
01037 std::vector<int> bitsPerSample;
01038 switch (img.type()) {
01039 case RGB24:
01040 photometricInterpretation = TIFF_PhotometricInterpretation_RGB;
01041 samplesPerPixel = 3;
01042 bitsPerSample = std::vector<int>(3,8);
01043 break;
01044 case RGB16:
01045 photometricInterpretation = TIFF_PhotometricInterpretation_RGB;
01046 samplesPerPixel = 3;
01047 bitsPerSample.push_back(5);
01048 bitsPerSample.push_back(6);
01049 bitsPerSample.push_back(5);
01050 break;
01051 case UYVY:
01052 case YUV24:
01053 error(Event::FileSaveError, "TIFFFile::Ifd::writeImage: UYVY/YUV images not supported yet.\n");
01054 return false;
01055 break;
01056 case RAW:
01057 photometricInterpretation = TIFF_PhotometricInterpretation_CFA;
01058 samplesPerPixel = 1;
01059 bitsPerSample.push_back(16);
01060 break;
01061 case UNKNOWN:
01062 error(Event::FileSaveError,
01063 "TIFFFile::Ifd::writeImage: Can't save UNKNOWN images.");
01064 return false;
01065 break;
01066 }
01067
01068 int width = img.width();
01069 int height = img.height();
01070
01071 const uint32_t targetBytesPerStrip = 64 * 1024;
01072 const uint32_t minRowsPerStrip = 10;
01073
01074 uint32_t bytesPerRow = img.bytesPerPixel() * width;
01075 int rowsPerStrip;
01076 if (minRowsPerStrip*bytesPerRow > targetBytesPerStrip) {
01077 rowsPerStrip = minRowsPerStrip;
01078 } else {
01079 rowsPerStrip = targetBytesPerStrip / bytesPerRow;
01080 }
01081 uint32_t stripsPerImage = height / rowsPerStrip;
01082 if (height % rowsPerStrip != 0) stripsPerImage++;
01083
01084 std::vector<int> stripOffsets;
01085 std::vector<int> stripByteCounts;
01086
01087 for (int ys=0; ys < height; ys += rowsPerStrip) {
01088 size_t lastRow = std::min(height, ys + rowsPerStrip);
01089 int bytesToWrite = (lastRow - ys) * bytesPerRow;
01090
01091 stripOffsets.push_back(ftell(fw));
01092 stripByteCounts.push_back(bytesToWrite);
01093
01094 int bytesWritten = 0;
01095 for (size_t y=ys; y < lastRow; y++) {
01096 bytesWritten += fwrite(img(0,y), sizeof(uint8_t), bytesPerRow, fw);
01097 }
01098 if (bytesWritten != bytesToWrite) {
01099 error(Event::FileSaveError, "TIFFFile::Ifd::writeImage: Unable to write image data to file (wanted to write %d bytes, able to write %d).", bytesToWrite, bytesWritten);
01100 return false;
01101 }
01102 }
01103
01104 bool success;
01105 success = add(TIFF_TAG_PhotometricInterpretation, photometricInterpretation);
01106 if (success) success = add(TIFF_TAG_SamplesPerPixel, samplesPerPixel);
01107 if (success) success = add(TIFF_TAG_BitsPerSample, bitsPerSample);
01108
01109 if (success) success = add(TIFF_TAG_ImageWidth, width);
01110 if (success) success = add(TIFF_TAG_ImageLength, height);
01111 if (success) success = add(TIFF_TAG_RowsPerStrip, rowsPerStrip);
01112
01113 if (success) success = add(TIFF_TAG_StripOffsets, stripOffsets);
01114 if (success) success = add(TIFF_TAG_StripByteCounts, stripByteCounts);
01115 if (success) success = add(TIFF_TAG_Orientation, TIFF_Orientation_TopLeft);
01116
01117 if (!success) {
01118 error(Event::FileSaveError,
01119 "TIFFFile::Ifd::writeImage: Can't add needed tags to IFD");
01120 return false;
01121 }
01122
01123 dprintf(5, "TIFFile::Ifd::writeImage: Image written.\n");
01124 return true;
01125 }
01126
01127
01128
01129
01130 TIFFFile::TIFFFile(): valid(false), fp(NULL), offsetToIfd0(0) {
01131 }
01132
01133 TIFFFile::TIFFFile(const std::string &file): valid(false), fp(NULL), offsetToIfd0(0) {
01134 readFrom(file);
01135 }
01136
01137 TIFFFile::~TIFFFile() {
01138 eraseIfds();
01139 if (fp) fclose(fp);
01140 }
01141
01142 bool TIFFFile::readFrom(const std::string &file) {
01143 dprintf(DBG_MINOR, "TIFFFile::readFrom(): Starting read of %s\n", file.c_str());
01144
01145
01146 if (fp) {
01147 fclose(fp); fp = NULL;
01148 }
01149 eraseIfds();
01150
01151 valid = false;
01152
01153
01154 fp = fopen(file.c_str(), "rb");
01155 filename = file;
01156 if (fp == NULL) {
01157 std::stringstream errMsg;
01158 errMsg << "Unable to open file: "<<strerror(errno);
01159 setError("readFrom", errMsg.str());
01160 return false;
01161 }
01162
01163
01164
01165 bool success = readHeader();
01166 if (!success) return false;
01167
01168 uint32_t nextIfdOffset = offsetToIfd0;
01169 while (nextIfdOffset != 0) {
01170 Ifd *ifd = new Ifd(this);
01171 success = readIfd(nextIfdOffset, ifd, &nextIfdOffset);
01172 if (!success) {
01173 delete ifd;
01174 return false;
01175 }
01176 _ifds.push_back(ifd);
01177 }
01178
01179 valid = true;
01180 return true;
01181 }
01182
01183 bool TIFFFile::writeTo(const std::string &file) {
01184 dprintf(4, "TIFFile::writeTo: %s: Beginning write\n", file.c_str());
01185
01186 if (ifds().size() == 0) {
01187 error(Event::FileSaveError,
01188 "TIFFFile::writeTo: %s: Nothing to write",
01189 file.c_str());
01190 return false;
01191 }
01192 FILE *fw = NULL;
01193 fw = fopen(file.c_str(), "wb");
01194 if (!fw) {
01195 error(Event::FileSaveError,
01196 "TIFFFile::writeTo: %s: Can't open file for writing",
01197 file.c_str());
01198 return false;
01199 }
01200
01201
01202 int count = 0;
01203 uint32_t headerOffset = 0;
01204 count = fwrite(&littleEndianMarker, sizeof(littleEndianMarker), 1, fw);
01205 if (count == 1)
01206 count = fwrite(&tiffMagicNumber, sizeof(tiffMagicNumber), 1 , fw);
01207
01208 uint32_t headerIfd0Offset = ftell(fw);
01209 if (count == 1)
01210 count = fwrite(&headerOffset, sizeof(headerOffset), 1, fw);
01211 if (count != 1) {
01212 error(Event::FileSaveError,
01213 "TIFFFile::writeTo: %s: Can't write TIFF file header",
01214 file.c_str());
01215 fclose(fw);
01216 return false;
01217 }
01218
01219
01220 bool success;
01221 uint32_t nextIfdOffset = 0;
01222 for (size_t i=ifds().size(); i > 0; i--) {
01223 dprintf(4, "TIFFile::writeTo: %s: Writing IFD %d\n", file.c_str(), i-1);
01224 success = ifds(i-1)->write(fw, nextIfdOffset, &nextIfdOffset);
01225 if (!success) {
01226 error(Event::FileSaveError,
01227 "TIFFFile::writeTo: %s: Can't write entry data blocks",
01228 file.c_str());
01229 fclose(fw);
01230 return false;
01231 }
01232 }
01233
01234
01235 fseek(fw, headerIfd0Offset, SEEK_SET);
01236 count = fwrite(&nextIfdOffset, sizeof(uint32_t), 1, fw);
01237 if (count != 1) {
01238 error(Event::FileSaveError,
01239 "TIFFFile::writeTo: %s: Can't write Ifd offset into header",
01240 file.c_str());
01241 fclose(fw);
01242 return false;
01243 }
01244
01245 fclose(fw);
01246 return true;
01247 }
01248
01249 TIFFFile::Ifd* TIFFFile::addIfd() {
01250 Ifd *ifd = new Ifd(this);
01251 _ifds.push_back(ifd);
01252 return ifd;
01253 }
01254
01255 void TIFFFile::eraseIfds() {
01256 for (size_t i=0; i < _ifds.size(); i++) {
01257 delete _ifds[i];
01258 }
01259 _ifds.clear();
01260 }
01261
01262 const std::vector<TIFFFile::Ifd *>& TIFFFile::ifds() const {
01263 return _ifds;
01264 }
01265
01266 TIFFFile::Ifd* TIFFFile::ifds(int index) {
01267 return _ifds[index];
01268 }
01269
01270
01271
01272
01273 bool TIFFFile::readHeader() {
01274
01275 fseek(fp, 0, SEEK_SET);
01276
01277 int count;
01278 uint16_t byteOrder, tiffHeaderNumber;
01279 count = fread(&byteOrder, sizeof(byteOrder), 1, fp);
01280 if (count == 1)
01281 count = fread(&tiffHeaderNumber, sizeof(tiffHeaderNumber), 1, fp);
01282 if (count == 1)
01283 count = fread(&offsetToIfd0, sizeof(offsetToIfd0), 1, fp);
01284 if (count != 1) {
01285 setError("readHeader", "Unable to read TIFF header!");
01286 fclose(fp); fp = NULL;
01287 return false;
01288 }
01289
01290
01291 if (byteOrder == littleEndianMarker) {
01292 littleEndian = true;
01293 } else if (byteOrder == bigEndianMarker) {
01294 littleEndian = false;
01295 } else {
01296 setError("readHeader", "Malformed TIFF header");
01297 fclose(fp); fp = NULL;
01298 return false;
01299 }
01300 dprintf(4, "TIFFFile::readHeader(): %s is %s-endian\n", filename.c_str(), littleEndian ? "little" : "big");
01301
01302
01303 tiffHeaderNumber = convShort(&tiffHeaderNumber);
01304 if (tiffHeaderNumber != tiffMagicNumber) {
01305 std::stringstream errMsg;
01306 errMsg << "TIFF header magic number is incorrect. This is not a valid TIFF or DNG file. (got "
01307 <<tiffHeaderNumber<<", expected "<<tiffMagicNumber;
01308 setError("readHeader", errMsg.str());
01309 fclose(fp); fp = NULL;
01310 return false;
01311 }
01312
01313
01314 offsetToIfd0 = convLong(&offsetToIfd0);
01315 dprintf(4, "TIFFFile::readHeader(): %s: IFD0 offset is 0x%x\n", filename.c_str(), offsetToIfd0);
01316
01317 return true;
01318 }
01319
01320 bool TIFFFile::readIfd(uint32_t offsetToIFD, Ifd *ifd, uint32_t *offsetToNextIFD) {
01321 int err;
01322
01323 err = fseek(fp, offsetToIFD, SEEK_SET);
01324 if (err != 0) {
01325 std::stringstream errMsg;
01326 errMsg << "Unable to seek to IFD at "<<offsetToIFD << ": "<<strerror(errno);
01327 setError("readIfd", errMsg.str());
01328 fclose(fp); fp = NULL;
01329 return false;
01330 }
01331
01332
01333 int count;
01334 uint16_t ifdEntries;
01335 count = fread(&ifdEntries, sizeof(uint16_t), 1, fp);
01336 if (count != 1) {
01337 std::stringstream errMsg;
01338 errMsg << "Unable to read header for IFD at "<<offsetToIFD;
01339 setError("readIfd", errMsg.str());
01340 fclose(fp); fp = NULL;
01341 return false;
01342 }
01343 ifdEntries = convShort(&ifdEntries);
01344 dprintf(4, "TIFFFile::readIfd(): In %s, IFD at 0x%x contains %d entries\n", filename.c_str(), (int)offsetToIFD, (int)ifdEntries);
01345
01346
01347 for (int i=0; i < ifdEntries; i++) {
01348 TiffIfdEntry entry;
01349 count = fread(&entry.tag, sizeof(entry.tag), 1, fp);
01350 if (count == 1)
01351 count = fread(&entry.type, sizeof(entry.type), 1, fp);
01352 if (count == 1)
01353 count = fread(&entry.count, sizeof(entry.count), 1, fp);
01354 if (count == 1)
01355 count = fread(&entry.offset, sizeof(entry.offset), 1, fp);
01356 if (count != 1) {
01357 std::stringstream errMsg;
01358 errMsg << "Unable to read IFD entry "<<i <<" for IFD at "<<offsetToIFD;
01359 setError("readIfd", errMsg.str());
01360 fclose(fp); fp = NULL;
01361 return false;
01362 }
01363 entry.tag = convShort(&entry.tag);
01364 entry.type = convShort(&entry.type);
01365 entry.count = convLong(&entry.count);
01366
01367 dprintf(5, "TIFFFile::readIfd(): IFD entry %d: Tag: %d (%s), Type: %d, Count: %d, Offset: 0x%x\n",
01368 i, entry.tag, tiffEntryLookup(entry.tag) == NULL ? "Unknown" : tiffEntryLookup(entry.tag)->name, entry.type, entry.count, entry.offset);
01369 ifd->add(entry);
01370 }
01371
01372
01373 if (offsetToNextIFD) {
01374 count = fread(offsetToNextIFD, sizeof(uint32_t), 1, fp);
01375 if (count != 1) {
01376 std::stringstream errMsg;
01377 errMsg << "Unable to read next-IFD offset field for IFD at "<<offsetToIFD;
01378 setError("readIfd", errMsg.str());
01379 fclose(fp); fp = NULL;
01380 return false;
01381 }
01382 *offsetToNextIFD = convLong(offsetToNextIFD);
01383 dprintf(DBG_MINOR, "TIFFFile::readIfd(): In file %s, IFD at %x has next-IFD offset field of %x\n",
01384 filename.c_str(), offsetToIFD, *offsetToNextIFD);
01385 }
01386
01387 bool success = readSubIfds(ifd);
01388
01389 return success;
01390 }
01391
01392 bool TIFFFile::readSubIfds(Ifd *ifd) {
01393
01394 ifd->eraseSubIfds();
01395
01396 bool success;
01397 const IfdEntry *subIfdEntry = ifd->find(TIFF_TAG_SubIFDs);
01398 if (subIfdEntry) {
01399 TagValue val = subIfdEntry->value();
01400 if (!val.valid()) {
01401 fclose(fp); fp = NULL;
01402 return false;
01403 }
01404 std::vector<int> subIfdOffsets;
01405 if (val.type == TagValue::Int) {
01406 subIfdOffsets.push_back(val.asInt());
01407 } else {
01408 subIfdOffsets = val;
01409 }
01410 dprintf(DBG_MINOR, "TIFFFile::readSubIfds(): %s: IFD has %d subIFDs\n",
01411 filename.c_str(), subIfdOffsets.size());
01412 for (unsigned int i=0; i < subIfdOffsets.size(); i++) {
01413 Ifd *subIfd = ifd->addSubIfd();
01414
01415 success = readIfd(subIfdOffsets[i], subIfd, NULL);
01416 if (!success) {
01417 return false;
01418 }
01419 }
01420 }
01421
01422 return true;
01423 }
01424
01425 uint16_t TIFFFile::convShort(void const *src) {
01426 uint16_t s = *(uint16_t const *)src;
01427 if (!littleEndian) s = (s << 8) || (s >> 8);
01428 return s;
01429 }
01430
01431 uint32_t TIFFFile::convLong(void const *src) {
01432 uint32_t l = *(uint32_t const *)src;
01433 if (!littleEndian) l = ((l & 0x000000FF) << 24) ||
01434 ((l & 0x0000FF00) << 8 ) ||
01435 ((l & 0x00FF0000) >> 8 ) ||
01436 ((l & 0xFF000000) >> 24 );
01437 return l;
01438 }
01439
01440 float TIFFFile::convFloat(void const *src) {
01441 return *reinterpret_cast<float *>(convLong(src));
01442 }
01443
01444 double TIFFFile::convDouble(void const *src) {
01445 double d;
01446 if (!littleEndian) {
01447 uint8_t *ptr = reinterpret_cast<uint8_t *>(&d);
01448 for (int i=0;i< 8;i++) {
01449 *(ptr++) = *(((uint8_t const *)src)+7-i);
01450 }
01451 } else {
01452 d = *reinterpret_cast<double const *>(src);
01453 }
01454 return d;
01455 }
01456
01457 bool TIFFFile::readByteArray(uint32_t offset, uint32_t count, uint8_t *dest) {
01458 if (!dest) return false;
01459
01460 int err = fseek(fp, offset, SEEK_SET);
01461 if (err != 0) {
01462 return false;
01463 }
01464 size_t trueCount = fread(dest, sizeof(uint8_t), count, fp);
01465 if (trueCount != count) return false;
01466
01467 return true;
01468 }
01469
01470 bool TIFFFile::readShortArray(uint32_t offset, uint32_t count, uint16_t *dest) {
01471 if (!dest) return false;
01472
01473 int err = fseek(fp, offset, SEEK_SET);
01474 if (err != 0) {
01475 return false;
01476 }
01477 size_t trueCount = fread(dest, sizeof(uint16_t), count, fp);
01478 if (trueCount != count) return false;
01479
01480 if (!littleEndian) {
01481 for (size_t i=0; i < count; i++) {
01482 uint16_t s = dest[i];
01483 dest[i] = (s << 8) || (s >> 8);
01484 }
01485 }
01486 return true;
01487 }
01488
01489 TIFFRational TIFFFile::convRational(void const *src) {
01490 TIFFRational r;
01491 r.numerator = convLong(src);
01492 r.denominator = convLong((unsigned char *)src+4);
01493 return r;
01494 }
01495
01496
01497 }