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 if (entry.type == TIFF_RATIONAL && vd < 0 ) {
00401 vd = 0;
00402 warning(Event::FileSaveWarning, "IfdEntry: Entry value less than zero when writing a RATIONAL entry. Clamped to zero.");
00403 }
00404
00405 int32_t num = vd * (1 << 20);
00406 int32_t den = 1 << 20;
00407 written = fwrite(&num, sizeof(int32_t), 1, fw);
00408 written += fwrite(&den, sizeof(int32_t), 1, fw);
00409 written /= 2;
00410 } else {
00411 std::vector<double> &vd = v;
00412 written = 0;
00413 for (size_t i=0; i < vd.size(); i++) {
00414 if (entry.type == TIFF_RATIONAL && vd[i] < 0 ) {
00415 vd[i] = 0;
00416 warning(Event::FileSaveWarning, "IfdEntry: Entry value less than zero when writing a RATIONAL entry. Clamped to zero.");
00417 }
00418 int32_t num = vd[i] * (1 << 20);
00419 int32_t den = 1 << 20;
00420 written += fwrite(&num, sizeof(int32_t), 1, fw);
00421 written += fwrite(&den, sizeof(int32_t), 1, fw);
00422 }
00423 written /= 2;
00424 }
00425 break;
00426 }
00427 case TIFF_SBYTE: {
00428 if (v.type == TagValue::IntVector) {
00429 std::vector<int> &vi = v;
00430 std::vector<int8_t> bytes(vi.begin(), vi.end());
00431 written = fwrite(&bytes[0], sizeof(int8_t), elements, fw);
00432 } else {
00433 std::string &vs = v;
00434 written = fwrite(vs.data(), sizeof(int8_t), elements, fw);
00435 }
00436 break;
00437 }
00438 case TIFF_UNDEFINED: {
00439 std::string &vs = v;
00440 written = fwrite(vs.data(), sizeof(int8_t), elements, fw);
00441 break;
00442 }
00443 case TIFF_SSHORT: {
00444 std::vector<int> &vi = v;
00445 std::vector<int16_t> shorts(vi.begin(), vi.end());
00446 written = fwrite(&shorts[0], sizeof(int16_t), elements, fw);
00447 break;
00448 }
00449 case TIFF_SLONG: {
00450 std::vector<int> &vi = v;
00451 written = fwrite(&vi[0], sizeof(uint32_t), elements, fw);
00452 break;
00453 }
00454 case TIFF_FLOAT: {
00455 std::vector<float> &vf = v;
00456 written = fwrite(&vf[0], sizeof(float), elements, fw);
00457 break;
00458 }
00459 case TIFF_DOUBLE: {
00460 if (elements == 1) {
00461 double vd = v;
00462 written = fwrite(&vd, sizeof(double), elements, fw);
00463 } else {
00464 std::vector<double> &vd = v;
00465 written = fwrite(&vd[0], sizeof(double), elements, fw);
00466 }
00467 break;
00468 }
00469 }
00470 if (written != elements) {
00471 error(Event::FileSaveError, "TIFFFile::IfdEntry::writeDataBlock: Can't write data to file (tried to write %d, only wrote %d)", elements, written);
00472 return false;
00473 }
00474 }
00475
00476 return true;
00477 }
00478
00479 bool TIFFFile::IfdEntry::write(FILE *fw) {
00480 dprintf(5, "TIFFile::IfdEntry::write: Writing tag entry %d (%s): %d %d %d\n", tag(), name(), entry.type, entry.count, entry.offset);
00481 int count;
00482 count = fwrite(&entry.tag, sizeof(entry.tag), 1, fw);
00483 if (count == 1) fwrite(&entry.type, sizeof(entry.type), 1, fw);
00484 if (count == 1) fwrite(&entry.count, sizeof(entry.count), 1, fw);
00485 if (count == 1) fwrite(&entry.offset, sizeof(entry.offset), 1, fw);
00486
00487 if (count != 1) {
00488 error(Event::FileSaveError, "TIFFile::IfdEntry::write: Can't write IFD entry to file.");
00489 return false;
00490 }
00491 return true;
00492
00493 }
00494
00495 bool TIFFFile::IfdEntry::operator<(const IfdEntry &other) const {
00496 return tag() < other.tag();
00497 }
00498
00499 TagValue TIFFFile::IfdEntry::parse() const {
00500 TagValue tag;
00501
00502 if (info != NULL) {
00503
00504 bool typeMismatch=false;
00505 switch(info->type) {
00506 case TIFF_BYTE:
00507 case TIFF_SHORT:
00508 case TIFF_LONG:
00509
00510 if (entry.type != TIFF_BYTE &&
00511 entry.type != TIFF_SHORT &&
00512 entry.type != TIFF_LONG)
00513 typeMismatch = true;
00514 break;
00515 case TIFF_SBYTE:
00516 case TIFF_SSHORT:
00517 case TIFF_SLONG:
00518
00519 if (entry.type != TIFF_SBYTE &&
00520 entry.type != TIFF_SSHORT &&
00521 entry.type != TIFF_SLONG)
00522 typeMismatch = true;
00523 break;
00524 case TIFF_ASCII:
00525 case TIFF_RATIONAL:
00526 case TIFF_UNDEFINED:
00527 case TIFF_SRATIONAL:
00528 case TIFF_FLOAT:
00529 case TIFF_DOUBLE:
00530
00531 if (entry.type != info->type) typeMismatch = true;
00532 break;
00533 case TIFF_IFD:
00534
00535 if (entry.type != TIFF_LONG &&
00536 entry.type != TIFF_IFD) typeMismatch = true;
00537 break;
00538 }
00539 if (typeMismatch) {
00540 warning(Event::FileLoadWarning,
00541 "In %s, type mismatch reading TIFF tag %d (%s), expected type %d, got %d\n",
00542 parent->filename.c_str(), entry.tag, info->name, info->type, entry.type);
00543 return tag;
00544 }
00545 }
00546
00547 unsigned int bytesPerElement=0;
00548 switch (entry.type) {
00549 case TIFF_BYTE: bytesPerElement = 1; break;
00550 case TIFF_ASCII: bytesPerElement = 1; break;
00551 case TIFF_SHORT: bytesPerElement = 2; break;
00552 case TIFF_LONG: bytesPerElement = 4; break;
00553 case TIFF_RATIONAL: bytesPerElement = 8; break;
00554 case TIFF_SBYTE: bytesPerElement = 1; break;
00555 case TIFF_UNDEFINED: bytesPerElement = 1; break;
00556 case TIFF_SSHORT: bytesPerElement = 2; break;
00557 case TIFF_SLONG: bytesPerElement = 4; break;
00558 case TIFF_SRATIONAL: bytesPerElement = 8; break;
00559 case TIFF_FLOAT: bytesPerElement = 4; break;
00560 case TIFF_DOUBLE: bytesPerElement = 8; break;
00561 case TIFF_IFD: bytesPerElement = 4; break;
00562 }
00563 unsigned int totalBytes = entry.count*bytesPerElement;
00564 std::vector<uint8_t> data(totalBytes);
00565
00566
00567 if (entry.count > 4/bytesPerElement) {
00568
00569 int adjOffset = parent->convLong(&entry.offset);
00570 bool success = parent->readByteArray(adjOffset, totalBytes, &data[0]);
00571 if (!success) {
00572 warning(Event::FileLoadWarning,
00573 "In %s, unable to read TIFF tag %d (%s) data at offset 0x%x\n",
00574 parent->filename.c_str(), entry.tag, name(), entry.offset);
00575 return tag;
00576 }
00577 } else {
00578 uint8_t *ptr = (uint8_t*)&entry.offset;
00579 for (size_t i=0; i < data.size(); i++) {
00580 data[i] = *(ptr++);
00581 }
00582 }
00583
00584 switch (entry.type) {
00585 case TIFF_BYTE:
00586 case TIFF_SBYTE:
00587 case TIFF_UNDEFINED:
00588 tag = std::string(data.begin(), data.end());
00589 break;
00590 case TIFF_ASCII: {
00591
00592 std::vector<std::string> strings;
00593 std::vector<uint8_t>::iterator start = data.begin();
00594 for (std::vector<uint8_t>::iterator it=data.begin(); it < data.end(); it++) {
00595 if (*it == 0) {
00596 strings.push_back(std::string(start, it));
00597 start = it + 1;
00598 }
00599 }
00600 if (strings.size() > 1) {
00601 tag = strings;
00602 } else {
00603 tag = strings[0];
00604 }
00605 break;
00606 }
00607 case TIFF_SHORT:
00608 if (entry.count > 1) {
00609 std::vector<int> vals(entry.count);
00610 uint8_t *ptr = &data[0];
00611 for (size_t i=0; i < entry.count; i++) {
00612 vals[i] = parent->convShort(ptr);
00613 ptr+=bytesPerElement;
00614 }
00615 tag = vals;
00616 } else {
00617 tag = parent->convShort(&data[0]);
00618 }
00619 break;
00620 case TIFF_IFD:
00621 case TIFF_LONG:
00622
00623 if (entry.count > 1) {
00624 std::vector<int> vals(entry.count);
00625 uint8_t *ptr = &data[0];
00626 for (size_t i=0; i < entry.count; i++) {
00627 vals[i] = (int)parent->convLong(ptr);
00628 ptr+=bytesPerElement;
00629 }
00630 tag = vals;
00631 } else {
00632 tag = (int)parent->convLong(&data[0]);
00633 }
00634 break;
00635 case TIFF_RATIONAL:
00636 if (entry.count > 1) {
00637 std::vector<double> vals(entry.count);
00638 uint8_t *ptr = &data[0];
00639 for (size_t i=0; i < entry.count; i++) {
00640 TIFFRational r = parent->convRational(ptr);
00641
00642 vals[i] = ((double)r.numerator)/((double)r.denominator);
00643 ptr+=bytesPerElement;
00644 }
00645 tag = vals;
00646 } else {
00647 TIFFRational r = parent->convRational(&data[0]);
00648 tag = ((double)r.numerator)/((double)r.denominator);
00649 }
00650 break;
00651 case TIFF_SSHORT:
00652 if (entry.count > 1) {
00653 std::vector<int> vals(entry.count);
00654 uint8_t *ptr = &data[0];
00655 for (size_t i=0; i < entry.count; i++) {
00656 uint16_t val = parent->convShort(ptr);
00657 vals[i] = *reinterpret_cast<int16_t *>(&val);
00658 ptr+=bytesPerElement;
00659 }
00660 tag = vals;
00661 } else {
00662 uint16_t val = parent->convShort(&data[0]);
00663 tag = *reinterpret_cast<int16_t *>(&val);
00664 }
00665 break;
00666
00667 case TIFF_SLONG:
00668 if (entry.count > 1) {
00669 std::vector<int> vals(entry.count);
00670 uint8_t *ptr = &data[0];
00671 for (size_t i=0; i < entry.count; i++) {
00672 uint32_t val = parent->convLong(ptr);
00673 vals[i] = *reinterpret_cast<int32_t *>(&val);
00674 ptr+=bytesPerElement;
00675 }
00676 tag = vals;
00677 } else {
00678 uint32_t val = parent->convLong(&data[0]);
00679 tag = *reinterpret_cast<int32_t *>(&val);
00680 }
00681 break;
00682 case TIFF_SRATIONAL:
00683 if (entry.count > 1) {
00684 std::vector<double> vals(entry.count);
00685 uint8_t *ptr = &data[0];
00686 for (size_t i=0; i < entry.count; i++) {
00687 TIFFRational r = parent->convRational(ptr);
00688
00689 vals[i] = (static_cast<double>(*reinterpret_cast<int32_t *>(&r.numerator)))
00690 /(static_cast<double>(*reinterpret_cast<int32_t *>(&r.denominator)));
00691 ptr+=bytesPerElement;
00692 }
00693 tag = vals;
00694 } else {
00695 TIFFRational r = parent->convRational(&data[0]);
00696 tag = (static_cast<double>(*reinterpret_cast<int32_t *>(&r.numerator)))
00697 /(static_cast<double>(*reinterpret_cast<int32_t *>(&r.denominator)));
00698 }
00699 break;
00700 case TIFF_FLOAT:
00701 if (entry.count > 1) {
00702 std::vector<float> vals(entry.count);
00703 uint8_t *ptr = &data[0];
00704 for (size_t i=0; i < entry.count; i++) {
00705 vals[i] = parent->convFloat(ptr);
00706 ptr+=bytesPerElement;
00707 }
00708 tag = vals;
00709 } else {
00710 tag = parent->convFloat(&data[0]);
00711 }
00712 break;
00713 case TIFF_DOUBLE:
00714 if (entry.count > 1) {
00715 std::vector<double> vals(entry.count);
00716 uint8_t *ptr = &data[0];
00717 for (size_t i=0; i < entry.count; i++) {
00718 vals[i] = parent->convDouble(ptr);
00719 ptr+=bytesPerElement;
00720 }
00721 tag = vals;
00722 } else {
00723 tag = parent->convDouble(&data[0]);
00724 }
00725 break;
00726 };
00727
00728 state = READ;
00729
00730 return tag;
00731 }
00732
00733
00734
00735
00736
00737 TIFFFile::Ifd::Ifd(TIFFFile *parent): parent(parent), imgState(UNREAD) {
00738 }
00739
00740 TIFFFile::Ifd::~Ifd() {
00741 eraseSubIfds();
00742 }
00743
00744 const TIFFFile::IfdEntry* TIFFFile::Ifd::find(uint16_t tag) const {
00745 entryMap::const_iterator match;
00746 match=entries.find(tag);
00747 if (match == entries.end()) return NULL;
00748 else return &(match->second);
00749 }
00750
00751 TIFFFile::IfdEntry* TIFFFile::Ifd::find(uint16_t tag) {
00752 entryMap::iterator match;
00753 match=entries.find(tag);
00754 if (match == entries.end()) return NULL;
00755 else return &(match->second);
00756 }
00757
00758 bool TIFFFile::Ifd::add(const TiffIfdEntry &rawEntry) {
00759 IfdEntry entry(rawEntry, parent);
00760
00761 entries.insert(entries.end(), entryMap::value_type(rawEntry.tag, entry));
00762 return true;
00763 }
00764
00765 bool TIFFFile::Ifd::add(uint16_t tag, const TagValue &val) {
00766 IfdEntry entry(tag, val, parent);
00767 if (!entry.valid()) return false;
00768 IfdEntry *existingEntry = find(tag);
00769 if (existingEntry) existingEntry->setValue(val);
00770 else {
00771 entries.insert(entryMap::value_type(tag, entry));
00772 }
00773 return true;
00774 }
00775
00776 bool TIFFFile::Ifd::add(const std::string &tagName, const TagValue &val) {
00777 const TiffEntryInfo *info = tiffEntryLookup(tagName);
00778 if (info) {
00779 return add(info->tag, val);
00780 }
00781 return false;
00782 }
00783
00784 TIFFFile::Ifd* TIFFFile::Ifd::addSubIfd() {
00785 Ifd *ifd = new Ifd(parent);
00786 _subIfds.push_back(ifd);
00787 return ifd;
00788 }
00789
00790 void TIFFFile::Ifd::eraseSubIfds() {
00791 for (size_t i=0; i < _subIfds.size(); i++) {
00792 delete _subIfds[i];
00793 }
00794 _subIfds.clear();
00795 }
00796
00797 const std::vector<TIFFFile::Ifd *>& TIFFFile::Ifd::subIfds() {
00798 return _subIfds;
00799 }
00800
00801 TIFFFile::Ifd* TIFFFile::Ifd::subIfds(int index) {
00802 return _subIfds[index];
00803 }
00804
00805 Image TIFFFile::Ifd::getImage() {
00806 if (imgState == NONE || imgState == CACHED) return imgCache;
00807
00808 const IfdEntry *entry;
00809
00810 const char *file = parent->filename.c_str();
00811
00812 entry = find(TIFF_TAG_PhotometricInterpretation);
00813 if (!entry) {
00814 imgState = NONE;
00815 return imgCache;
00816 }
00817 int photometricInterpretation = entry->value();
00818
00819 #define fatalError(...) \
00820 do { \
00821 warning(Event::FileLoadError, __VA_ARGS__); \
00822 imgState = NONE; \
00823 return imgCache; \
00824 } while(0);
00825
00826 ImageFormat fmt = UNKNOWN;
00827 switch (photometricInterpretation) {
00828 case TIFF_PhotometricInterpretation_WhiteIsZero:
00829 case TIFF_PhotometricInterpretation_BlackIsZero:
00830 case TIFF_PhotometricInterpretation_PaletteRGB:
00831 case TIFF_PhotometricInterpretation_TransparencyMask:
00832 case TIFF_PhotometricInterpretation_CMYK:
00833 case TIFF_PhotometricInterpretation_CIELAB:
00834 case TIFF_PhotometricInterpretation_ICCLAB:
00835 case TIFF_PhotometricInterpretation_ITULAB:
00836 case TIFF_PhotometricInterpretation_YCbCr:
00837
00838 fatalError("Ifd::getImage(): %s: Unsupported pixel format (PhotometricInterpretation) %d.",
00839 file,
00840 photometricInterpretation);
00841 break;
00842 case TIFF_PhotometricInterpretation_RGB:
00843 fmt = RGB24;
00844 break;
00845 case TIFF_PhotometricInterpretation_LinearRaw:
00846 fatalError("Ifd::getImage(): %s: Linear RAW is not supported.",
00847 file);
00848 break;
00849 case TIFF_PhotometricInterpretation_CFA:
00850 fmt = RAW;
00851 break;
00852
00853 }
00854
00855 int compression = TIFF_Compression_DEFAULT;
00856 entry = find(TIFF_TAG_Compression);
00857 if (entry) compression = entry->value();
00858
00859 switch (compression) {
00860 case TIFF_Compression_Uncompressed:
00861
00862 break;
00863 default:
00864 fatalError("Ifd::getImage(): %s: Unsupported compression type %d.",
00865 file,
00866 compression);
00867 break;
00868 }
00869
00870
00871 int samplesPerPixel = TIFF_SamplesPerPixel_DEFAULT;
00872 entry = find(TIFF_TAG_SamplesPerPixel);
00873 if (entry) samplesPerPixel = entry->value();
00874 switch (fmt) {
00875 case RAW:
00876 if (samplesPerPixel != 1) {
00877 fatalError("Ifd::getImage(): %s: RAW images cannot have more than 1 sample per pixel.",
00878 file);
00879 }
00880 break;
00881 case RGB24:
00882 if (samplesPerPixel != 3) {
00883 fatalError("Ifd::getImage(): %s: RGB24 images must have 3 samples per pixel", file);
00884 }
00885 break;
00886 default:
00887 fatalError("Ifd::getImage(): %s: Unexpected branch in the road", file);
00888 break;
00889 }
00890
00891 entry = find(TIFF_TAG_BitsPerSample);
00892 if (!entry) fatalError("Ifd::getImage(): %s: No BitsPerSample entry found.", file);
00893
00894 switch (fmt) {
00895 case RAW: {
00896 int bitsPerSample = entry->value();
00897 if (bitsPerSample != 16) fatalError("Ifd::getImage(): %s: Only 16-bpp RAW images supported.", file);
00898 break;
00899 }
00900 case RGB24: {
00901 std::vector<int> bitsPerSample = entry->value();
00902 if (bitsPerSample[0] != 8 ||
00903 bitsPerSample[1] != 8||
00904 bitsPerSample[2] != 8) fatalError("Ifd::getImage(): %s: Only 24-bpp RGB images supported.", file);
00905 break;
00906 }
00907 default:
00908 fatalError("Ifd::getImage(): %s: Unexpected branch in the road", file);
00909 break;
00910 }
00911
00912 entry = find(TIFF_TAG_Orientation);
00913 if (!entry) fatalError("Ifd::getImage(): %s: No orientation entry found, required for RAW.", file);
00914 int orientation = entry->value();
00915
00916 if (orientation != 1) fatalError("Ifd::getImage(): %s: Unsupported orientation value %d", file, orientation);
00917
00918
00919 entry = find(TIFF_TAG_ImageWidth);
00920 if (!entry) fatalError("Ifd::getImage(): %s: No ImageWidth entry found.", file);
00921 int imageWidth = entry->value();
00922
00923 entry = find(TIFF_TAG_ImageLength);
00924 if (!entry) fatalError("Ifd::getImage(): %s: No ImageLength entry found.", file);
00925 int imageLength = entry->value();
00926
00927 dprintf(4,"Ifd::getImage(): %s: Image size is %d x %d\n", file, imageWidth, imageLength);
00928
00929
00930 entry = find(TIFF_TAG_RowsPerStrip);
00931 int rowsPerStrip = TIFF_RowsPerStrip_DEFAULT;
00932 uint32_t stripsPerImage = 1;
00933 if (entry) {
00934 rowsPerStrip = entry->value();
00935 stripsPerImage = imageLength / rowsPerStrip;
00936 if (imageLength % rowsPerStrip != 0) stripsPerImage++;
00937 }
00938
00939 entry = find(TIFF_TAG_StripOffsets);
00940 if (!entry) fatalError("Ifd::getImage(): %s: No image strip data found, and tiled data is not supported.", file);
00941 std::vector<int> stripOffsets = entry->value();
00942 if (stripOffsets.size() != stripsPerImage)
00943 fatalError("Ifd::getImage(): %s: Malformed IFD - conflicting values on number of image strips.", file);
00944
00945 dprintf(5, "Ifd::getImage(): %s: Image data in %d strips of %d rows each.\n", file, stripsPerImage, rowsPerStrip);
00946
00947
00948
00949 Image img(imageWidth, imageLength, fmt);
00950
00951 uint32_t bytesPerStrip = rowsPerStrip * imageWidth * img.bytesPerPixel();
00952 uint32_t bytesLeft = imageLength * imageWidth * img.bytesPerPixel();
00953 for (uint32_t strip=0; strip < stripsPerImage; strip++) {
00954 uint32_t bytesToRead = std::min(bytesLeft, bytesPerStrip);
00955 bool success = parent->readByteArray(stripOffsets[strip], bytesToRead, img(0,rowsPerStrip*strip) );
00956 if (!success) {
00957 fatalError("Ifd::getImage(): %s: Cannot read in all image data.\n", file);
00958 }
00959 bytesLeft -= bytesToRead;
00960 }
00961
00962 #undef fatalError
00963
00964 imgCache = img;
00965 imgState = CACHED;
00966 return imgCache;
00967 }
00968
00969 bool TIFFFile::Ifd::setImage(Image newImg) {
00970 if (newImg.type() != RAW &&
00971 newImg.type() != RGB24) {
00972 error(Event::FileSaveError, "Ifd::setImage(): Can only save RAW or RGB24 images");
00973 return false;
00974 }
00975 imgCache = newImg;
00976 imgState = CACHED;
00977 return true;
00978 }
00979
00980 bool TIFFFile::Ifd::write(FILE *fw, uint32_t nextIfdOffset, uint32_t *offset) {
00981 bool success;
00982
00983 if (_subIfds.size() > 0) {
00984 std::vector<int> subIfdOffsets;
00985
00986 for (size_t i=0; i < _subIfds.size(); i++ ) {
00987 uint32_t subIfdOffset;
00988 dprintf(4, "TIFFile::Ifd::write: Writing subIFD %d\n", i);
00989 success = _subIfds[i]->write(fw, 0, &subIfdOffset);
00990 if (!success) return false;
00991 subIfdOffsets.push_back(subIfdOffset);
00992 }
00993
00994 IfdEntry *subIfdEntry = find(TIFF_TAG_SubIFDs);
00995 if (subIfdEntry != NULL) {
00996 success = subIfdEntry->setValue(TagValue(subIfdOffsets));
00997 } else {
00998 success = add(TIFF_TAG_SubIFDs, TagValue(subIfdOffsets));
00999 }
01000 if (!success) return false;
01001 }
01002
01003 success = writeImage(fw);
01004 if (!success) return false;
01005
01006
01007 dprintf(5, "TIFFile::Ifd::write: Writing Ifd entry data blocks.\n");
01008
01009 for (entryMap::iterator it=entries.begin(); it != entries.end(); it++) {
01010 success = it->second.writeDataBlock(fw);
01011 if (!success) return false;
01012 }
01013
01014
01015 *offset = ftell(fw);
01016
01017 int count;
01018 uint16_t entryCount = entries.size();
01019 count = fwrite(&entryCount, sizeof(uint16_t), 1, fw);
01020 if (count != 1) return false;
01021
01022 dprintf(5, "TIFFile::Ifd::write: Writing IFD entries\n");
01023 for (entryMap::iterator it=entries.begin(); it != entries.end(); it++) {
01024 success = it->second.write(fw);
01025 if (!success) return false;
01026 }
01027 count = fwrite(&nextIfdOffset, sizeof(uint32_t), 1, fw);
01028 if (count != 1) return false;
01029
01030 dprintf(5, "TIFFile::Ifd::write: IFD written\n");
01031 return true;
01032 }
01033
01034 bool TIFFFile::Ifd::writeImage(FILE *fw) {
01035 Image img = getImage();
01036 if (imgState == NONE) return true;
01037 dprintf(5, "TIFFile::Ifd::writeImage: Beginning image write\n");
01038 if (!img.valid()) {
01039 error(Event::FileSaveError, "TIFFFile::Ifd::writeImage: Invalid image");
01040 return false;
01041 }
01042
01043 int photometricInterpretation = 0;
01044 int samplesPerPixel = 0;
01045 std::vector<int> bitsPerSample;
01046 switch (img.type()) {
01047 case RGB24:
01048 photometricInterpretation = TIFF_PhotometricInterpretation_RGB;
01049 samplesPerPixel = 3;
01050 bitsPerSample = std::vector<int>(3,8);
01051 break;
01052 case RGB16:
01053 photometricInterpretation = TIFF_PhotometricInterpretation_RGB;
01054 samplesPerPixel = 3;
01055 bitsPerSample.push_back(5);
01056 bitsPerSample.push_back(6);
01057 bitsPerSample.push_back(5);
01058 break;
01059 case UYVY:
01060 case YUV24:
01061 error(Event::FileSaveError, "TIFFFile::Ifd::writeImage: UYVY/YUV images not supported yet.\n");
01062 return false;
01063 break;
01064 case RAW:
01065 photometricInterpretation = TIFF_PhotometricInterpretation_CFA;
01066 samplesPerPixel = 1;
01067 bitsPerSample.push_back(16);
01068 break;
01069 case UNKNOWN:
01070 error(Event::FileSaveError,
01071 "TIFFFile::Ifd::writeImage: Can't save UNKNOWN images.");
01072 return false;
01073 break;
01074 }
01075
01076 int width = img.width();
01077 int height = img.height();
01078
01079 const uint32_t targetBytesPerStrip = 64 * 1024;
01080 const uint32_t minRowsPerStrip = 10;
01081
01082 uint32_t bytesPerRow = img.bytesPerPixel() * width;
01083 int rowsPerStrip;
01084 if (minRowsPerStrip*bytesPerRow > targetBytesPerStrip) {
01085 rowsPerStrip = minRowsPerStrip;
01086 } else {
01087 rowsPerStrip = targetBytesPerStrip / bytesPerRow;
01088 }
01089 uint32_t stripsPerImage = height / rowsPerStrip;
01090 if (height % rowsPerStrip != 0) stripsPerImage++;
01091
01092 std::vector<int> stripOffsets;
01093 std::vector<int> stripByteCounts;
01094
01095 for (int ys=0; ys < height; ys += rowsPerStrip) {
01096 size_t lastRow = std::min(height, ys + rowsPerStrip);
01097 int bytesToWrite = (lastRow - ys) * bytesPerRow;
01098
01099 stripOffsets.push_back(ftell(fw));
01100 stripByteCounts.push_back(bytesToWrite);
01101
01102 int bytesWritten = 0;
01103 for (size_t y=ys; y < lastRow; y++) {
01104 bytesWritten += fwrite(img(0,y), sizeof(uint8_t), bytesPerRow, fw);
01105 }
01106 if (bytesWritten != bytesToWrite) {
01107 error(Event::FileSaveError, "TIFFFile::Ifd::writeImage: Unable to write image data to file (wanted to write %d bytes, able to write %d).", bytesToWrite, bytesWritten);
01108 return false;
01109 }
01110 }
01111
01112 bool success;
01113 success = add(TIFF_TAG_PhotometricInterpretation, photometricInterpretation);
01114 if (success) success = add(TIFF_TAG_SamplesPerPixel, samplesPerPixel);
01115 if (success) success = add(TIFF_TAG_BitsPerSample, bitsPerSample);
01116
01117 if (success) success = add(TIFF_TAG_ImageWidth, width);
01118 if (success) success = add(TIFF_TAG_ImageLength, height);
01119 if (success) success = add(TIFF_TAG_RowsPerStrip, rowsPerStrip);
01120
01121 if (success) success = add(TIFF_TAG_StripOffsets, stripOffsets);
01122 if (success) success = add(TIFF_TAG_StripByteCounts, stripByteCounts);
01123 if (success) success = add(TIFF_TAG_Orientation, TIFF_Orientation_TopLeft);
01124
01125 if (!success) {
01126 error(Event::FileSaveError,
01127 "TIFFFile::Ifd::writeImage: Can't add needed tags to IFD");
01128 return false;
01129 }
01130
01131 dprintf(5, "TIFFile::Ifd::writeImage: Image written.\n");
01132 return true;
01133 }
01134
01135
01136
01137
01138 TIFFFile::TIFFFile(): valid(false), fp(NULL), offsetToIfd0(0) {
01139 }
01140
01141 TIFFFile::TIFFFile(const std::string &file): valid(false), fp(NULL), offsetToIfd0(0) {
01142 readFrom(file);
01143 }
01144
01145 TIFFFile::~TIFFFile() {
01146 eraseIfds();
01147 if (fp) fclose(fp);
01148 }
01149
01150 bool TIFFFile::readFrom(const std::string &file) {
01151 dprintf(DBG_MINOR, "TIFFFile::readFrom(): Starting read of %s\n", file.c_str());
01152
01153
01154 if (fp) {
01155 fclose(fp); fp = NULL;
01156 }
01157 eraseIfds();
01158
01159 valid = false;
01160
01161
01162 fp = fopen(file.c_str(), "rb");
01163 filename = file;
01164 if (fp == NULL) {
01165 std::stringstream errMsg;
01166 errMsg << "Unable to open file: "<<strerror(errno);
01167 setError("readFrom", errMsg.str());
01168 return false;
01169 }
01170
01171
01172
01173 bool success = readHeader();
01174 if (!success) return false;
01175
01176 uint32_t nextIfdOffset = offsetToIfd0;
01177 while (nextIfdOffset != 0) {
01178 Ifd *ifd = new Ifd(this);
01179 success = readIfd(nextIfdOffset, ifd, &nextIfdOffset);
01180 if (!success) {
01181 delete ifd;
01182 return false;
01183 }
01184 _ifds.push_back(ifd);
01185 }
01186
01187 valid = true;
01188 return true;
01189 }
01190
01191 bool TIFFFile::writeTo(const std::string &file) {
01192 dprintf(4, "TIFFile::writeTo: %s: Beginning write\n", file.c_str());
01193
01194 if (ifds().size() == 0) {
01195 error(Event::FileSaveError,
01196 "TIFFFile::writeTo: %s: Nothing to write",
01197 file.c_str());
01198 return false;
01199 }
01200 FILE *fw = NULL;
01201 fw = fopen(file.c_str(), "wb");
01202 if (!fw) {
01203 error(Event::FileSaveError,
01204 "TIFFFile::writeTo: %s: Can't open file for writing",
01205 file.c_str());
01206 return false;
01207 }
01208
01209
01210 int count = 0;
01211 uint32_t headerOffset = 0;
01212 count = fwrite(&littleEndianMarker, sizeof(littleEndianMarker), 1, fw);
01213 if (count == 1)
01214 count = fwrite(&tiffMagicNumber, sizeof(tiffMagicNumber), 1 , fw);
01215
01216 uint32_t headerIfd0Offset = ftell(fw);
01217 if (count == 1)
01218 count = fwrite(&headerOffset, sizeof(headerOffset), 1, fw);
01219 if (count != 1) {
01220 error(Event::FileSaveError,
01221 "TIFFFile::writeTo: %s: Can't write TIFF file header",
01222 file.c_str());
01223 fclose(fw);
01224 return false;
01225 }
01226
01227
01228 bool success;
01229 uint32_t nextIfdOffset = 0;
01230 for (size_t i=ifds().size(); i > 0; i--) {
01231 dprintf(4, "TIFFile::writeTo: %s: Writing IFD %d\n", file.c_str(), i-1);
01232 success = ifds(i-1)->write(fw, nextIfdOffset, &nextIfdOffset);
01233 if (!success) {
01234 error(Event::FileSaveError,
01235 "TIFFFile::writeTo: %s: Can't write entry data blocks",
01236 file.c_str());
01237 fclose(fw);
01238 return false;
01239 }
01240 }
01241
01242
01243 fseek(fw, headerIfd0Offset, SEEK_SET);
01244 count = fwrite(&nextIfdOffset, sizeof(uint32_t), 1, fw);
01245 if (count != 1) {
01246 error(Event::FileSaveError,
01247 "TIFFFile::writeTo: %s: Can't write Ifd offset into header",
01248 file.c_str());
01249 fclose(fw);
01250 return false;
01251 }
01252
01253 fclose(fw);
01254 return true;
01255 }
01256
01257 TIFFFile::Ifd* TIFFFile::addIfd() {
01258 Ifd *ifd = new Ifd(this);
01259 _ifds.push_back(ifd);
01260 return ifd;
01261 }
01262
01263 void TIFFFile::eraseIfds() {
01264 for (size_t i=0; i < _ifds.size(); i++) {
01265 delete _ifds[i];
01266 }
01267 _ifds.clear();
01268 }
01269
01270 const std::vector<TIFFFile::Ifd *>& TIFFFile::ifds() const {
01271 return _ifds;
01272 }
01273
01274 TIFFFile::Ifd* TIFFFile::ifds(int index) {
01275 return _ifds[index];
01276 }
01277
01278
01279
01280
01281 bool TIFFFile::readHeader() {
01282
01283 fseek(fp, 0, SEEK_SET);
01284
01285 int count;
01286 uint16_t byteOrder, tiffHeaderNumber;
01287 count = fread(&byteOrder, sizeof(byteOrder), 1, fp);
01288 if (count == 1)
01289 count = fread(&tiffHeaderNumber, sizeof(tiffHeaderNumber), 1, fp);
01290 if (count == 1)
01291 count = fread(&offsetToIfd0, sizeof(offsetToIfd0), 1, fp);
01292 if (count != 1) {
01293 setError("readHeader", "Unable to read TIFF header!");
01294 fclose(fp); fp = NULL;
01295 return false;
01296 }
01297
01298
01299 if (byteOrder == littleEndianMarker) {
01300 littleEndian = true;
01301 } else if (byteOrder == bigEndianMarker) {
01302 littleEndian = false;
01303 } else {
01304 setError("readHeader", "Malformed TIFF header");
01305 fclose(fp); fp = NULL;
01306 return false;
01307 }
01308 dprintf(4, "TIFFFile::readHeader(): %s is %s-endian\n", filename.c_str(), littleEndian ? "little" : "big");
01309
01310
01311 tiffHeaderNumber = convShort(&tiffHeaderNumber);
01312 if (tiffHeaderNumber != tiffMagicNumber) {
01313 std::stringstream errMsg;
01314 errMsg << "TIFF header magic number is incorrect. This is not a valid TIFF or DNG file. (got "
01315 <<tiffHeaderNumber<<", expected "<<tiffMagicNumber;
01316 setError("readHeader", errMsg.str());
01317 fclose(fp); fp = NULL;
01318 return false;
01319 }
01320
01321
01322 offsetToIfd0 = convLong(&offsetToIfd0);
01323 dprintf(4, "TIFFFile::readHeader(): %s: IFD0 offset is 0x%x\n", filename.c_str(), offsetToIfd0);
01324
01325 return true;
01326 }
01327
01328 bool TIFFFile::readIfd(uint32_t offsetToIFD, Ifd *ifd, uint32_t *offsetToNextIFD) {
01329 int err;
01330
01331 err = fseek(fp, offsetToIFD, SEEK_SET);
01332 if (err != 0) {
01333 std::stringstream errMsg;
01334 errMsg << "Unable to seek to IFD at "<<offsetToIFD << ": "<<strerror(errno);
01335 setError("readIfd", errMsg.str());
01336 fclose(fp); fp = NULL;
01337 return false;
01338 }
01339
01340
01341 int count;
01342 uint16_t ifdEntries;
01343 count = fread(&ifdEntries, sizeof(uint16_t), 1, fp);
01344 if (count != 1) {
01345 std::stringstream errMsg;
01346 errMsg << "Unable to read header for IFD at "<<offsetToIFD;
01347 setError("readIfd", errMsg.str());
01348 fclose(fp); fp = NULL;
01349 return false;
01350 }
01351 ifdEntries = convShort(&ifdEntries);
01352 dprintf(4, "TIFFFile::readIfd(): In %s, IFD at 0x%x contains %d entries\n", filename.c_str(), (int)offsetToIFD, (int)ifdEntries);
01353
01354
01355 for (int i=0; i < ifdEntries; i++) {
01356 TiffIfdEntry entry;
01357 count = fread(&entry.tag, sizeof(entry.tag), 1, fp);
01358 if (count == 1)
01359 count = fread(&entry.type, sizeof(entry.type), 1, fp);
01360 if (count == 1)
01361 count = fread(&entry.count, sizeof(entry.count), 1, fp);
01362 if (count == 1)
01363 count = fread(&entry.offset, sizeof(entry.offset), 1, fp);
01364 if (count != 1) {
01365 std::stringstream errMsg;
01366 errMsg << "Unable to read IFD entry "<<i <<" for IFD at "<<offsetToIFD;
01367 setError("readIfd", errMsg.str());
01368 fclose(fp); fp = NULL;
01369 return false;
01370 }
01371 entry.tag = convShort(&entry.tag);
01372 entry.type = convShort(&entry.type);
01373 entry.count = convLong(&entry.count);
01374
01375 dprintf(5, "TIFFFile::readIfd(): IFD entry %d: Tag: %d (%s), Type: %d, Count: %d, Offset: 0x%x\n",
01376 i, entry.tag, tiffEntryLookup(entry.tag) == NULL ? "Unknown" : tiffEntryLookup(entry.tag)->name, entry.type, entry.count, entry.offset);
01377 ifd->add(entry);
01378 }
01379
01380
01381 if (offsetToNextIFD) {
01382 count = fread(offsetToNextIFD, sizeof(uint32_t), 1, fp);
01383 if (count != 1) {
01384 std::stringstream errMsg;
01385 errMsg << "Unable to read next-IFD offset field for IFD at "<<offsetToIFD;
01386 setError("readIfd", errMsg.str());
01387 fclose(fp); fp = NULL;
01388 return false;
01389 }
01390 *offsetToNextIFD = convLong(offsetToNextIFD);
01391 dprintf(DBG_MINOR, "TIFFFile::readIfd(): In file %s, IFD at %x has next-IFD offset field of %x\n",
01392 filename.c_str(), offsetToIFD, *offsetToNextIFD);
01393 }
01394
01395 bool success = readSubIfds(ifd);
01396
01397 return success;
01398 }
01399
01400 bool TIFFFile::readSubIfds(Ifd *ifd) {
01401
01402 ifd->eraseSubIfds();
01403
01404 bool success;
01405 const IfdEntry *subIfdEntry = ifd->find(TIFF_TAG_SubIFDs);
01406 if (subIfdEntry) {
01407 TagValue val = subIfdEntry->value();
01408 if (!val.valid()) {
01409 fclose(fp); fp = NULL;
01410 return false;
01411 }
01412 std::vector<int> subIfdOffsets;
01413 if (val.type == TagValue::Int) {
01414 subIfdOffsets.push_back(val.asInt());
01415 } else {
01416 subIfdOffsets = val;
01417 }
01418 dprintf(DBG_MINOR, "TIFFFile::readSubIfds(): %s: IFD has %d subIFDs\n",
01419 filename.c_str(), subIfdOffsets.size());
01420 for (unsigned int i=0; i < subIfdOffsets.size(); i++) {
01421 Ifd *subIfd = ifd->addSubIfd();
01422
01423 success = readIfd(subIfdOffsets[i], subIfd, NULL);
01424 if (!success) {
01425 return false;
01426 }
01427 }
01428 }
01429
01430 return true;
01431 }
01432
01433 uint16_t TIFFFile::convShort(void const *src) {
01434 uint16_t s = *(uint16_t const *)src;
01435 if (!littleEndian) s = (s << 8) || (s >> 8);
01436 return s;
01437 }
01438
01439 uint32_t TIFFFile::convLong(void const *src) {
01440 uint32_t l = *(uint32_t const *)src;
01441 if (!littleEndian) l = ((l & 0x000000FF) << 24) ||
01442 ((l & 0x0000FF00) << 8 ) ||
01443 ((l & 0x00FF0000) >> 8 ) ||
01444 ((l & 0xFF000000) >> 24 );
01445 return l;
01446 }
01447
01448 float TIFFFile::convFloat(void const *src) {
01449 return *reinterpret_cast<float *>(convLong(src));
01450 }
01451
01452 double TIFFFile::convDouble(void const *src) {
01453 double d;
01454 if (!littleEndian) {
01455 uint8_t *ptr = reinterpret_cast<uint8_t *>(&d);
01456 for (int i=0;i< 8;i++) {
01457 *(ptr++) = *(((uint8_t const *)src)+7-i);
01458 }
01459 } else {
01460 d = *reinterpret_cast<double const *>(src);
01461 }
01462 return d;
01463 }
01464
01465 bool TIFFFile::readByteArray(uint32_t offset, uint32_t count, uint8_t *dest) {
01466 if (!dest) return false;
01467
01468 int err = fseek(fp, offset, SEEK_SET);
01469 if (err != 0) {
01470 return false;
01471 }
01472 size_t trueCount = fread(dest, sizeof(uint8_t), count, fp);
01473 if (trueCount != count) return false;
01474
01475 return true;
01476 }
01477
01478 bool TIFFFile::readShortArray(uint32_t offset, uint32_t count, uint16_t *dest) {
01479 if (!dest) return false;
01480
01481 int err = fseek(fp, offset, SEEK_SET);
01482 if (err != 0) {
01483 return false;
01484 }
01485 size_t trueCount = fread(dest, sizeof(uint16_t), count, fp);
01486 if (trueCount != count) return false;
01487
01488 if (!littleEndian) {
01489 for (size_t i=0; i < count; i++) {
01490 uint16_t s = dest[i];
01491 dest[i] = (s << 8) || (s >> 8);
01492 }
01493 }
01494 return true;
01495 }
01496
01497 TIFFRational TIFFFile::convRational(void const *src) {
01498 TIFFRational r;
01499 r.numerator = convLong(src);
01500 r.denominator = convLong((unsigned char *)src+4);
01501 return r;
01502 }
01503
01504
01505 }