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