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 info = tiffEntryLookup(entry.tag);
00017 }
00018
00019 TiffIfdEntry::TiffIfdEntry(uint16_t tag, const TagValue &val, TiffFile *parent):
00020 entry(), info(NULL), parent(parent), state(INVALID), val(val) {
00021 entry.tag = tag;
00022 entry.count = 0;
00023 entry.offset = 0;
00024 info = tiffEntryLookup(tag);
00025 if (info) { entry.type = info->type; }
00026 setValue(val);
00027 }
00028
00029 TiffIfdEntry::TiffIfdEntry(uint16_t tag, TiffFile *parent): entry(), info(NULL), parent(parent), state(INVALID), val() {
00030 entry.tag = tag;
00031 }
00032
00033 bool TiffIfdEntry::valid() const {
00034 return state != INVALID;
00035 }
00036
00037 uint16_t TiffIfdEntry::tag() const {
00038 return entry.tag;
00039 }
00040
00041 const char *TiffIfdEntry::name() const {
00042 if (info == NULL) { return "UnknownTag"; }
00043 else { return info->name; }
00044 }
00045
00046 const TagValue &TiffIfdEntry::value() const {
00047 if (state == UNREAD) {
00048 val = parse();
00049 if (!val.valid()) { state = INVALID; }
00050 }
00051 return val;
00052 }
00053
00054 bool TiffIfdEntry::setValue(const TagValue &newVal) {
00055 if (info == NULL) {
00056 switch (newVal.type) {
00057 case TagValue::Null:
00058 warning(Event::FileSaveWarning, "TiffIfdEntry: NULL value passed in for tag %d", tag());
00059 state = INVALID;
00060 return false;
00061 break;
00062 case TagValue::Int:
00063 case TagValue::IntVector:
00064 entry.type = TIFF_SLONG;
00065 break;
00066 case TagValue::Float:
00067 case TagValue::FloatVector:
00068 entry.type = TIFF_FLOAT;
00069 break;
00070 case TagValue::Double:
00071 case TagValue::DoubleVector:
00072 entry.type = TIFF_DOUBLE;
00073 break;
00074 case TagValue::String:
00075 case TagValue::StringVector:
00076 entry.type = TIFF_ASCII;
00077 break;
00078 case TagValue::Time:
00079 case TagValue::TimeVector:
00080 warning(Event::FileSaveWarning, "TiffIfdEntry: Can't store TagValue::Time values in TIFF tag %d", tag());
00081 state = INVALID;
00082 val = TagValue();
00083 return false;
00084 break;
00085 }
00086 } else {
00087 bool typeMismatch = false;
00088 switch (newVal.type) {
00089 case TagValue::Null:
00090 warning(Event::FileSaveWarning, "TiffIfdEntry: NULL value passed in for tag %d", tag());
00091 state = INVALID;
00092 return false;
00093 break;
00094 case TagValue::Int:
00095 case TagValue::IntVector:
00096 if (entry.type != TIFF_BYTE &&
00097 entry.type != TIFF_SHORT &&
00098 entry.type != TIFF_LONG &&
00099 entry.type != TIFF_SBYTE &&
00100 entry.type != TIFF_SSHORT &&
00101 entry.type != TIFF_SLONG &&
00102 entry.type != TIFF_IFD) {
00103 typeMismatch= true;
00104 }
00105 break;
00106 case TagValue::Float:
00107 case TagValue::FloatVector:
00108 if (entry.type != TIFF_FLOAT &&
00109 entry.type != TIFF_DOUBLE) {
00110 typeMismatch= true;
00111 }
00112 break;
00113 case TagValue::Double:
00114 case TagValue::DoubleVector:
00115 if (entry.type != TIFF_DOUBLE &&
00116 entry.type != TIFF_FLOAT &&
00117 entry.type != TIFF_RATIONAL &&
00118 entry.type != TIFF_SRATIONAL) {
00119 typeMismatch= true;
00120 }
00121 break;
00122 case TagValue::String:
00123 case TagValue::StringVector:
00124 if (entry.type != TIFF_ASCII &&
00125 entry.type != TIFF_BYTE &&
00126 entry.type != TIFF_SBYTE) {
00127 typeMismatch= true;
00128 }
00129 break;
00130 case TagValue::Time:
00131 case TagValue::TimeVector:
00132 typeMismatch = true;
00133 break;
00134 }
00135 if (typeMismatch) {
00136 warning(Event::FileSaveWarning, "TiffIfdEntry: Trying to set tag %d (%s) of type %d to incompatible TagValue type %d",
00137 tag(), name(), entry.type, newVal.type);
00138 state = INVALID;
00139 return false;
00140 }
00141 }
00142 val = newVal;
00143 state = WRITTEN;
00144 return true;
00145 }
00146
00147 bool TiffIfdEntry::writeDataBlock(FILE *fw) {
00148 const TagValue &v = value();
00149 if (state == INVALID) {
00150 error(Event::FileSaveError,
00151 "TiffIfdEntry::writeDataBlock: Trying to write invalid tag %d (%s)",
00152 tag(), name());
00153 return false;
00154 }
00155
00156 unsigned int bytesPerElement=0;
00157 switch (entry.type) {
00158 case TIFF_BYTE: bytesPerElement = 1; break;
00159 case TIFF_ASCII: bytesPerElement = 1; break;
00160 case TIFF_SHORT: bytesPerElement = 2; break;
00161 case TIFF_LONG: bytesPerElement = 4; break;
00162 case TIFF_RATIONAL: bytesPerElement = 8; break;
00163 case TIFF_SBYTE: bytesPerElement = 1; break;
00164 case TIFF_UNDEFINED: bytesPerElement = 1; break;
00165 case TIFF_SSHORT: bytesPerElement = 2; break;
00166 case TIFF_SLONG: bytesPerElement = 4; break;
00167 case TIFF_SRATIONAL: bytesPerElement = 8; break;
00168 case TIFF_FLOAT: bytesPerElement = 4; break;
00169 case TIFF_DOUBLE: bytesPerElement = 8; break;
00170 case TIFF_IFD: bytesPerElement = 4; break;
00171 }
00172 unsigned int elements = 0;
00173 switch (v.type) {
00174 case TagValue::Int:
00175 case TagValue::Float:
00176 case TagValue::Double:
00177 elements = 1;
00178 break;
00179 case TagValue::IntVector: {
00180 std::vector<int> &vi = v;
00181 elements = vi.size();
00182 break;
00183 }
00184 case TagValue::FloatVector: {
00185 std::vector<float> &vf = v;
00186 elements = vf.size();
00187 break;
00188 }
00189 case TagValue::DoubleVector: {
00190 std::vector<double> &vd = v;
00191 elements = vd.size();
00192 break;
00193 }
00194 case TagValue::String: {
00195 std::string &vs = v;
00196 if (entry.type == TIFF_ASCII) {
00197 elements = vs.size() + 1;
00198 } else {
00199 elements = vs.size();
00200 }
00201 break;
00202 }
00203 case TagValue::StringVector: {
00204 std::vector<std::string> &strs = v;
00205 for (size_t i=0; i < strs.size(); i++) {
00206 elements += strs[i].size()+1;
00207 }
00208 break;
00209 }
00210 default:
00211 error(Event::FileSaveError, "TiffIfdEntry::writeDataBlock: Unexpected TagValue type.");
00212 return false;
00213 break;
00214 }
00215
00216 entry.count = elements;
00217
00218 uint32_t dataBytes = bytesPerElement * elements;
00219
00220 if (dataBytes <= 4) {
00221
00222 switch (entry.type) {
00223 case TIFF_BYTE: {
00224 uint8_t *off = (uint8_t *)&entry.offset;
00225 if (v.type == TagValue::Int) {
00226 uint8_t byte = (int)v;
00227 *off = byte;
00228 } else if (v.type == TagValue::IntVector) {
00229 std::vector<int> &bytes = v;
00230 for (size_t i=0; i < elements; i++) {
00231 *off++ = bytes[i];
00232 }
00233 } else {
00234 std::string &bytes = v;
00235 for (size_t i=0; i < elements; i++) {
00236 *off++ = bytes[i];
00237 }
00238 }
00239 break;
00240 }
00241 case TIFF_ASCII: {
00242 uint8_t *off = (uint8_t *)&entry.offset;
00243 if (v.type == TagValue::String) {
00244 std::string &ascii = v;
00245 for (size_t i=0; i < ascii.size(); i++) {
00246 *off++ = ascii[i];
00247 }
00248 *off = 0;
00249 } else {
00250 std::vector<std::string> &asciis = v;
00251 for (size_t i=0; i < asciis.size(); i++) {
00252 for (size_t j=0; j < asciis[i].size(); j++) {
00253 *off++ = asciis[i][j];
00254 }
00255 *off++ = 0;
00256 }
00257 }
00258 break;
00259 }
00260 case TIFF_SHORT: {
00261 uint16_t *off = (uint16_t *)(void *)&entry.offset;
00262 if (v.type == TagValue::Int) {
00263 uint16_t vs = (int)v;
00264 *off = vs;
00265 } else {
00266 std::vector<int> &shorts = v;
00267 for (size_t i=0; i < elements; i++) {
00268 *off++ = shorts[i];
00269 }
00270 }
00271 break;
00272 }
00273 case TIFF_IFD:
00274 case TIFF_LONG: {
00275 if (v.type == TagValue::Int) {
00276 uint32_t vs = (int)v;
00277 entry.offset = vs;
00278 } else {
00279 std::vector<int> &vi = v;
00280 entry.offset = (uint32_t)vi[0];
00281 }
00282 break;
00283 }
00284 case TIFF_SBYTE: {
00285 int8_t *off = (int8_t *)&entry.offset;
00286 if (v.type == TagValue::Int) {
00287 int8_t byte = (int)v;
00288 *off = byte;
00289 } else if (v.type == TagValue::IntVector) {
00290 std::vector<int> &bytes = v;
00291 for (size_t i=0; i < elements; i++) {
00292 *off++ = bytes[i];
00293 }
00294 } else {
00295 std::string &bytes = v;
00296 for (size_t i=0; i < elements; i++) {
00297 *off++ = bytes[i];
00298 }
00299 }
00300 break;
00301 }
00302 case TIFF_UNDEFINED: {
00303 uint8_t *off = (uint8_t *)&entry.offset;
00304 std::string &bytes = v;
00305 for (size_t i=0; i < elements; i++) {
00306 *off++ = bytes[i];
00307 }
00308 break;
00309 }
00310 case TIFF_SSHORT: {
00311 int16_t *off = (int16_t *)(void *)&entry.offset;
00312 if (v.type == TagValue::Int) {
00313 int16_t vs = (int)v;
00314 *off = vs;
00315 } else {
00316 std::vector<int> &shorts = v;
00317 for (size_t i=0; i < elements; i++) {
00318 *off++ = shorts[i];
00319 }
00320 }
00321 break;
00322 }
00323 case TIFF_SLONG: {
00324 if (v.type == TagValue::Int) {
00325 int32_t vs = (int)v;
00326 entry.offset = vs;
00327 } else {
00328 std::vector<int> &vi = v;
00329 entry.offset = vi[0];
00330 }
00331 break;
00332 }
00333 case TIFF_FLOAT: {
00334 float *off = (float *)(void *)&entry.offset;
00335 if (v.type == TagValue::Float) {
00336 float vf = v;
00337 *off = vf;
00338 } else {
00339 std::vector<float> &vf = v;
00340 *off = vf[0];
00341 }
00342 break;
00343 }
00344 }
00345 } else {
00346
00347
00348
00349
00350
00351 #if FCAM_DEBUG_LEVEL >= 6
00352 dprintf(6, "TiffFileEntry::writeDataBlock: Tag %d (%s) data: %s\n", entry.tag, name(), v.toString().substr(0,200).c_str());
00353 #else
00354 dprintf(5, "TiffFileEntry::writeDataBlock: Writing tag %d (%s) data block.\n", entry.tag, name());
00355 #endif
00356
00357 entry.offset = ftell(fw);
00358
00359 if ((entry.offset & 0x1) == 1) {
00360 uint8_t padding = 0x00;
00361 fwrite(&padding, sizeof(uint8_t), 1, fw);
00362 entry.offset = ftell(fw);
00363 }
00364
00365 size_t written = 0;
00366 switch (entry.type) {
00367 case TIFF_BYTE: {
00368 if (v.type == TagValue::IntVector) {
00369 std::vector<int> &vi = v;
00370 std::vector<uint8_t> bytes(vi.begin(), vi.end());
00371 written = fwrite(&bytes[0], sizeof(uint8_t), elements, fw);
00372 } else {
00373 std::string &vs = v;
00374 written = fwrite(vs.data(), sizeof(uint8_t), elements, fw);
00375 }
00376 break;
00377 }
00378 case TIFF_ASCII: {
00379 if (v.type == TagValue::String) {
00380 std::string &ascii = v;
00381 written = fwrite(ascii.c_str(), sizeof(char), elements, fw);
00382 } else {
00383 std::vector<std::string> &asciis = v;
00384 for (size_t i=0; i < asciis.size(); i++) {
00385 written += fwrite(asciis[i].c_str(), sizeof(char), asciis[i].size()+1, fw);
00386 }
00387 }
00388 break;
00389 }
00390 case TIFF_SHORT: {
00391 std::vector<int> &vi = v;
00392 std::vector<uint16_t> shorts(vi.begin(), vi.end());
00393 written = fwrite(&shorts[0], sizeof(uint16_t), shorts.size(), fw);
00394 break;
00395 }
00396 case TIFF_IFD:
00397 case TIFF_LONG: {
00398 std::vector<int> &vi = v;
00399 written = fwrite(&vi[0], sizeof(uint32_t), vi.size(), fw);
00400 break;
00401 }
00402 case TIFF_SRATIONAL:
00403 case TIFF_RATIONAL: {
00404 if (v.type == TagValue::Double) {
00405 double vd = v;
00406 if (entry.type == TIFF_RATIONAL && vd < 0) {
00407 vd = 0;
00408 warning(Event::FileSaveWarning, "TiffIfdEntry: Entry value less than zero when writing a RATIONAL entry. Clamped to zero.");
00409 }
00410
00411 int32_t num = vd * (1 << 20);
00412 int32_t den = 1 << 20;
00413 written = fwrite(&num, sizeof(int32_t), 1, fw);
00414 written += fwrite(&den, sizeof(int32_t), 1, fw);
00415 written /= 2;
00416 } else {
00417 std::vector<double> &vd = v;
00418 written = 0;
00419 for (size_t i=0; i < vd.size(); i++) {
00420 if (entry.type == TIFF_RATIONAL && vd[i] < 0) {
00421 vd[i] = 0;
00422 warning(Event::FileSaveWarning, "TiffIfdEntry: Entry value less than zero when writing a RATIONAL entry. Clamped to zero.");
00423 }
00424 int32_t num = vd[i] * (1 << 20);
00425 int32_t den = 1 << 20;
00426 written += fwrite(&num, sizeof(int32_t), 1, fw);
00427 written += fwrite(&den, sizeof(int32_t), 1, fw);
00428 }
00429 written /= 2;
00430 }
00431 break;
00432 }
00433 case TIFF_SBYTE: {
00434 if (v.type == TagValue::IntVector) {
00435 std::vector<int> &vi = v;
00436 std::vector<int8_t> bytes(vi.begin(), vi.end());
00437 written = fwrite(&bytes[0], sizeof(int8_t), elements, fw);
00438 } else {
00439 std::string &vs = v;
00440 written = fwrite(vs.data(), sizeof(int8_t), elements, fw);
00441 }
00442 break;
00443 }
00444 case TIFF_UNDEFINED: {
00445 std::string &vs = v;
00446 written = fwrite(vs.data(), sizeof(int8_t), elements, fw);
00447 break;
00448 }
00449 case TIFF_SSHORT: {
00450 std::vector<int> &vi = v;
00451 std::vector<int16_t> shorts(vi.begin(), vi.end());
00452 written = fwrite(&shorts[0], sizeof(int16_t), elements, fw);
00453 break;
00454 }
00455 case TIFF_SLONG: {
00456 std::vector<int> &vi = v;
00457 written = fwrite(&vi[0], sizeof(uint32_t), elements, fw);
00458 break;
00459 }
00460 case TIFF_FLOAT: {
00461 std::vector<float> &vf = v;
00462 written = fwrite(&vf[0], sizeof(float), elements, fw);
00463 break;
00464 }
00465 case TIFF_DOUBLE: {
00466 if (elements == 1) {
00467 double vd = v;
00468 written = fwrite(&vd, sizeof(double), elements, fw);
00469 } else {
00470 std::vector<double> &vd = v;
00471 written = fwrite(&vd[0], sizeof(double), elements, fw);
00472 }
00473 break;
00474 }
00475 }
00476 if (written != elements) {
00477 error(Event::FileSaveError, "TiffIfdEntry::writeDataBlock: Can't write data to file (tried to write %d, only wrote %d)", elements, written);
00478 return false;
00479 }
00480 }
00481
00482 return true;
00483 }
00484
00485 bool TiffIfdEntry::write(FILE *fw) {
00486 dprintf(5, "TIFFile::IfdEntry::write: Writing tag entry %d (%s): %d %d %d\n", tag(), name(), entry.type, entry.count, entry.offset);
00487 int count;
00488
00489
00490 uint16_t compatType = entry.type;
00491 if (compatType == TIFF_IFD) {
00492 compatType = TIFF_LONG;
00493 }
00494
00495 count = fwrite(&entry.tag, sizeof(entry.tag), 1, fw);
00496 if (count == 1) { fwrite(&compatType, sizeof(compatType), 1, fw); }
00497 if (count == 1) { fwrite(&entry.count, sizeof(entry.count), 1, fw); }
00498 if (count == 1) { fwrite(&entry.offset, sizeof(entry.offset), 1, fw); }
00499
00500 if (count != 1) {
00501 error(Event::FileSaveError, "TIFFile::IfdEntry::write: Can't write IFD entry to file.");
00502 return false;
00503 }
00504 return true;
00505
00506 }
00507
00508 bool TiffIfdEntry::operator<(const TiffIfdEntry &other) const {
00509 return tag() < other.tag();
00510 }
00511
00512 TagValue TiffIfdEntry::parse() const {
00513 TagValue tag;
00514
00515 if (info != NULL) {
00516
00517 bool typeMismatch=false;
00518 switch (info->type) {
00519 case TIFF_BYTE:
00520 case TIFF_SHORT:
00521 case TIFF_LONG:
00522
00523 if (entry.type != TIFF_BYTE &&
00524 entry.type != TIFF_SHORT &&
00525 entry.type != TIFF_LONG) {
00526 typeMismatch = true;
00527 }
00528 break;
00529 case TIFF_SBYTE:
00530 case TIFF_SSHORT:
00531 case TIFF_SLONG:
00532
00533 if (entry.type != TIFF_SBYTE &&
00534 entry.type != TIFF_SSHORT &&
00535 entry.type != TIFF_SLONG) {
00536 typeMismatch = true;
00537 }
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
00966 dprintf(5, "TiffIfd::getImage(): %s: Image data in %d strips of %d rows each.\n", file, stripsPerImage, rowsPerStrip);
00967
00968 uint32_t bytesPerStrip = rowsPerStrip * imageWidth * bytesPerPixel(fmt);
00969 uint32_t bytesLeft = imageLength * imageWidth * bytesPerPixel(fmt);
00970
00971
00972 if (memMap) {
00973 for (uint32_t strip=0; strip < stripsPerImage-1; strip++) {
00974 if (stripOffsets[strip]+(int)bytesPerStrip != stripOffsets[strip+1]) {
00975 memMap = false;
00976 warning(Event::FileLoadError, "TiffIfd::getImage(): %s: Memory mapped I/O was requested but TIFF image data is not contiguous.", file);
00977 break;
00978 }
00979 }
00980 }
00981
00982 if (!memMap) {
00983
00984
00985 Image img(imageWidth, imageLength, fmt);
00986
00987 for (uint32_t strip=0; strip < stripsPerImage; strip++) {
00988 uint32_t bytesToRead = std::min(bytesLeft, bytesPerStrip);
00989 bool success = parent->readByteArray(stripOffsets[strip],
00990 bytesToRead,
00991 img(0,rowsPerStrip*strip));
00992 if (!success) {
00993 fatalError("TiffIfd::getImage(): %s: Cannot read in all image data.\n", file);
00994 }
00995 bytesLeft -= bytesToRead;
00996 }
00997
00998 imgCache = img;
00999 imgState = CACHED;
01000 } else {
01001
01002 dprintf(5, "TiffIfd::getImage(): %s: Memmapping Image at %x, %x bytes\n",
01003 file, stripOffsets[0], bytesPerPixel(fmt)*imageWidth*imageLength);
01004 imgCache = Image(fileno(parent->fp),
01005 stripOffsets[0],
01006 Size(imageWidth, imageLength),
01007 fmt);
01008 }
01009 #undef fatalError
01010
01011 return imgCache;
01012 }
01013
01014 bool TiffIfd::setImage(Image newImg) {
01015 if (newImg.type() != RAW &&
01016 newImg.type() != RGB24) {
01017 error(Event::FileSaveError, "TiffIfd::setImage(): Can only save RAW or RGB24 images");
01018 return false;
01019 }
01020 imgCache = newImg;
01021 imgState = CACHED;
01022 return true;
01023 }
01024
01025 bool TiffIfd::write(FILE *fw, uint32_t nextIfdOffset, uint32_t *offset) {
01026 bool success;
01027
01028 if (_subIfds.size() > 0) {
01029 std::vector<int> subIfdOffsets;
01030
01031 for (size_t i=0; i < _subIfds.size(); i++) {
01032 uint32_t subIfdOffset;
01033 dprintf(4, "TiffIfd::write: Writing subIFD %d\n", i);
01034 success = _subIfds[i]->write(fw, 0, &subIfdOffset);
01035 if (!success) { return false; }
01036 subIfdOffsets.push_back(subIfdOffset);
01037 }
01038
01039 TiffIfdEntry *subIfdEntry = find(TIFF_TAG_SubIFDs);
01040 if (subIfdEntry != NULL) {
01041 success = subIfdEntry->setValue(TagValue(subIfdOffsets));
01042 } else {
01043 success = add(TIFF_TAG_SubIFDs, TagValue(subIfdOffsets));
01044 }
01045 if (!success) { return false; }
01046 }
01047
01048 if (exifIfd != NULL) {
01049 dprintf(4, "TiffIfd::write: Writing exif IFD\n\n");
01050 uint32_t exifIfdOffset;
01051 success = exifIfd->write(fw, 0, &exifIfdOffset);
01052 if (!success) { return false; }
01053 success = add(EXIF_TAG_ExifIfd, (int)exifIfdOffset);
01054 }
01055
01056
01057 success = writeImage(fw);
01058 if (!success) { return false; }
01059
01060
01061 dprintf(5, "TiffIfd::write: Writing Ifd entry data blocks.\n");
01062
01063 for (entryMap::iterator it=entries.begin(); it != entries.end(); it++) {
01064 success = it->second.writeDataBlock(fw);
01065 if (!success) { return false; }
01066 }
01067
01068
01069 *offset = ftell(fw);
01070
01071 if ((*offset & 0x1) == 1) {
01072 uint8_t padding = 0x00;
01073 fwrite(&padding, sizeof(uint8_t), 1, fw);
01074 *offset = ftell(fw);
01075 }
01076
01077
01078 int count;
01079 uint16_t entryCount = entries.size();
01080 count = fwrite(&entryCount, sizeof(uint16_t), 1, fw);
01081 if (count != 1) { return false; }
01082
01083 dprintf(5, "TiffIfd::write: Writing IFD entries\n");
01084 for (entryMap::iterator it=entries.begin(); it != entries.end(); it++) {
01085 success = it->second.write(fw);
01086 if (!success) { return false; }
01087 }
01088 count = fwrite(&nextIfdOffset, sizeof(uint32_t), 1, fw);
01089 if (count != 1) { return false; }
01090
01091 dprintf(5, "TiffIfd::write: IFD written\n");
01092 return true;
01093 }
01094
01095 bool TiffIfd::writeImage(FILE *fw) {
01096 Image img = getImage();
01097 if (imgState == NONE) { return true; }
01098 dprintf(5, "TiffIfd::writeImage: Beginning image write\n");
01099 if (!img.valid()) {
01100 error(Event::FileSaveError, "TiffIfd::writeImage: Invalid image");
01101 return false;
01102 }
01103
01104 int photometricInterpretation = 0;
01105 int samplesPerPixel = 0;
01106 std::vector<int> bitsPerSample;
01107 switch (img.type()) {
01108 case RGB24:
01109 photometricInterpretation = TIFF_PhotometricInterpretation_RGB;
01110 samplesPerPixel = 3;
01111 bitsPerSample = std::vector<int>(3,8);
01112 break;
01113 case RGB16:
01114 photometricInterpretation = TIFF_PhotometricInterpretation_RGB;
01115 samplesPerPixel = 3;
01116 bitsPerSample.push_back(5);
01117 bitsPerSample.push_back(6);
01118 bitsPerSample.push_back(5);
01119 break;
01120 case UYVY:
01121 case YUV24:
01122 error(Event::FileSaveError, "TiffIfd::writeImage: UYVY/YUV images not supported yet.\n");
01123 return false;
01124 break;
01125 case RAW:
01126 photometricInterpretation = TIFF_PhotometricInterpretation_CFA;
01127 samplesPerPixel = 1;
01128 bitsPerSample.push_back(16);
01129 break;
01130 case UNKNOWN:
01131 error(Event::FileSaveError,
01132 "TiffIfd::writeImage: Can't save UNKNOWN images.");
01133 return false;
01134 break;
01135 }
01136
01137 int width = img.width();
01138 int height = img.height();
01139
01140 const uint32_t targetBytesPerStrip = 64 * 1024;
01141 const uint32_t minRowsPerStrip = 10;
01142
01143 uint32_t bytesPerRow = img.bytesPerPixel() * width;
01144 int rowsPerStrip;
01145 if (minRowsPerStrip*bytesPerRow > targetBytesPerStrip) {
01146 rowsPerStrip = minRowsPerStrip;
01147 } else {
01148 rowsPerStrip = targetBytesPerStrip / bytesPerRow;
01149 }
01150 uint32_t stripsPerImage = height / rowsPerStrip;
01151 if (height % rowsPerStrip != 0) { stripsPerImage++; }
01152
01153 std::vector<int> stripOffsets;
01154 std::vector<int> stripByteCounts;
01155
01156 for (int ys=0; ys < height; ys += rowsPerStrip) {
01157 size_t lastRow = std::min(height, ys + rowsPerStrip);
01158 int bytesToWrite = (lastRow - ys) * bytesPerRow;
01159
01160 stripOffsets.push_back(ftell(fw));
01161 stripByteCounts.push_back(bytesToWrite);
01162
01163 int bytesWritten = 0;
01164 for (size_t y=ys; y < lastRow; y++) {
01165 bytesWritten += fwrite(img(0,y), sizeof(uint8_t), bytesPerRow, fw);
01166 }
01167 if (bytesWritten != bytesToWrite) {
01168 error(Event::FileSaveError, "TiffIfd::writeImage: Unable to write image data to file (wanted to write %d bytes, able to write %d).", bytesToWrite, bytesWritten);
01169 return false;
01170 }
01171 }
01172
01173 bool success;
01174 success = add(TIFF_TAG_PhotometricInterpretation, photometricInterpretation);
01175 if (success) { success = add(TIFF_TAG_SamplesPerPixel, samplesPerPixel); }
01176 if (success) { success = add(TIFF_TAG_BitsPerSample, bitsPerSample); }
01177
01178 if (success) { success = add(TIFF_TAG_ImageWidth, width); }
01179 if (success) { success = add(TIFF_TAG_ImageLength, height); }
01180 if (success) { success = add(TIFF_TAG_RowsPerStrip, rowsPerStrip); }
01181
01182 if (success) { success = add(TIFF_TAG_StripOffsets, stripOffsets); }
01183 if (success) { success = add(TIFF_TAG_StripByteCounts, stripByteCounts); }
01184
01185 if (success) { success = add(TIFF_TAG_Compression, TIFF_Compression_Uncompressed); }
01186
01187 if (!success) {
01188 error(Event::FileSaveError,
01189 "TiffIfd::writeImage: Can't add needed tags to IFD");
01190 return false;
01191 }
01192
01193 dprintf(5, "TiffIfd::writeImage: Image written.\n");
01194 return true;
01195 }
01196
01197
01198
01199
01200 TiffFile::TiffFile(): valid(false), fp(NULL), offsetToIfd0(0) {
01201 }
01202
01203 TiffFile::TiffFile(const std::string &file): valid(false), fp(NULL), offsetToIfd0(0) {
01204 readFrom(file);
01205 }
01206
01207 TiffFile::~TiffFile() {
01208 eraseIfds();
01209 if (fp) { fclose(fp); }
01210 }
01211
01212 bool TiffFile::readFrom(const std::string &file) {
01213 dprintf(DBG_MINOR, "TiffFile::readFrom(): Starting read of %s\n", file.c_str());
01214
01215
01216 if (fp) {
01217 fclose(fp); fp = NULL;
01218 }
01219 eraseIfds();
01220
01221 valid = false;
01222
01223
01224 fp = fopen(file.c_str(), "rb");
01225 _filename = file;
01226 if (fp == NULL) {
01227 std::stringstream errMsg;
01228 errMsg << "Unable to open file: "<<strerror(errno);
01229 setError("readFrom", errMsg.str());
01230 return false;
01231 }
01232
01233
01234
01235 bool success = readHeader();
01236 if (!success) { return false; }
01237
01238 uint32_t nextIfdOffset = offsetToIfd0;
01239 while (nextIfdOffset != 0) {
01240 TiffIfd *ifd = new TiffIfd(this);
01241 success = readIfd(nextIfdOffset, ifd, &nextIfdOffset);
01242 if (!success) {
01243 delete ifd;
01244 return false;
01245 }
01246 _ifds.push_back(ifd);
01247 }
01248
01249 valid = true;
01250 return true;
01251 }
01252
01253 bool TiffFile::writeTo(const std::string &file) {
01254 dprintf(4, "TIFFile::writeTo: %s: Beginning write\n", file.c_str());
01255
01256 if (ifds().size() == 0) {
01257 error(Event::FileSaveError,
01258 "TiffFile::writeTo: %s: Nothing to write",
01259 file.c_str());
01260 return false;
01261 }
01262 FILE *fw = NULL;
01263 fw = fopen(file.c_str(), "wb");
01264 if (!fw) {
01265 error(Event::FileSaveError,
01266 "TiffFile::writeTo: %s: Can't open file for writing",
01267 file.c_str());
01268 return false;
01269 }
01270
01271
01272 int count = 0;
01273 uint32_t headerOffset = 0;
01274 count = fwrite(&littleEndianMarker, sizeof(littleEndianMarker), 1, fw);
01275 if (count == 1) {
01276 count = fwrite(&tiffMagicNumber, sizeof(tiffMagicNumber), 1 , fw);
01277 }
01278
01279 uint32_t headerIfd0Offset = ftell(fw);
01280 if (count == 1) {
01281 count = fwrite(&headerOffset, sizeof(headerOffset), 1, fw);
01282 }
01283 if (count != 1) {
01284 error(Event::FileSaveError,
01285 "TiffFile::writeTo: %s: Can't write TIFF file header",
01286 file.c_str());
01287 fclose(fw);
01288 return false;
01289 }
01290
01291
01292 bool success;
01293 uint32_t nextIfdOffset = 0;
01294 for (size_t i=ifds().size(); i > 0; i--) {
01295 dprintf(4, "TIFFile::writeTo: %s: Writing IFD %d\n", file.c_str(), i-1);
01296 success = ifds(i-1)->write(fw, nextIfdOffset, &nextIfdOffset);
01297 if (!success) {
01298 error(Event::FileSaveError,
01299 "TiffFile::writeTo: %s: Can't write entry data blocks",
01300 file.c_str());
01301 fclose(fw);
01302 return false;
01303 }
01304 }
01305
01306
01307 fseek(fw, headerIfd0Offset, SEEK_SET);
01308 count = fwrite(&nextIfdOffset, sizeof(uint32_t), 1, fw);
01309 if (count != 1) {
01310 error(Event::FileSaveError,
01311 "TiffFile::writeTo: %s: Can't write Ifd offset into header",
01312 file.c_str());
01313 fclose(fw);
01314 return false;
01315 }
01316
01317 fclose(fw);
01318 return true;
01319 }
01320
01321 const std::string &TiffFile::filename() const {
01322 return _filename;
01323 }
01324
01325 TiffIfd *TiffFile::addIfd() {
01326 TiffIfd *ifd = new TiffIfd(this);
01327 _ifds.push_back(ifd);
01328 return ifd;
01329 }
01330
01331 void TiffFile::eraseIfds() {
01332 for (size_t i=0; i < _ifds.size(); i++) {
01333 delete _ifds[i];
01334 }
01335 _ifds.clear();
01336 }
01337
01338 const std::vector<TiffIfd *>& TiffFile::ifds() const {
01339 return _ifds;
01340 }
01341
01342 TiffIfd *TiffFile::ifds(int index) {
01343 return _ifds[index];
01344 }
01345
01346
01347
01348
01349 bool TiffFile::readHeader() {
01350
01351 fseek(fp, 0, SEEK_SET);
01352
01353 int count;
01354 uint16_t byteOrder, tiffHeaderNumber;
01355 count = fread(&byteOrder, sizeof(byteOrder), 1, fp);
01356 if (count == 1) {
01357 count = fread(&tiffHeaderNumber, sizeof(tiffHeaderNumber), 1, fp);
01358 }
01359 if (count == 1) {
01360 count = fread(&offsetToIfd0, sizeof(offsetToIfd0), 1, fp);
01361 }
01362 if (count != 1) {
01363 setError("readHeader", "Unable to read TIFF header!");
01364 fclose(fp); fp = NULL;
01365 return false;
01366 }
01367
01368
01369 if (byteOrder == littleEndianMarker) {
01370 littleEndian = true;
01371 } else if (byteOrder == bigEndianMarker) {
01372 littleEndian = false;
01373 } else {
01374 setError("readHeader", "Malformed TIFF header");
01375 fclose(fp); fp = NULL;
01376 return false;
01377 }
01378 dprintf(4, "TiffFile::readHeader(): %s is %s-endian\n", filename().c_str(), littleEndian ? "little" : "big");
01379
01380
01381 tiffHeaderNumber = convShort(&tiffHeaderNumber);
01382 if (tiffHeaderNumber != tiffMagicNumber) {
01383 std::stringstream errMsg;
01384 errMsg << "TIFF header magic number is incorrect. This is not a valid TIFF or DNG file. (got "
01385 <<tiffHeaderNumber<<", expected "<<tiffMagicNumber;
01386 setError("readHeader", errMsg.str());
01387 fclose(fp); fp = NULL;
01388 return false;
01389 }
01390
01391
01392 offsetToIfd0 = convLong(&offsetToIfd0);
01393 dprintf(4, "TiffFile::readHeader(): %s: IFD0 offset is 0x%x\n", filename().c_str(), offsetToIfd0);
01394
01395
01396 if (offsetToIfd0 < 8) {
01397 std::stringstream errMsg;
01398 errMsg << "Offset to first IFD in TIFF file is " << offsetToIfd0
01399 << ". This is not a valid TIFF or DNG file.";
01400 setError("readHeader", errMsg.str());
01401 fclose(fp); fp = NULL;
01402 return false;
01403 }
01404
01405 return true;
01406 }
01407
01408 bool TiffFile::readIfd(uint32_t offsetToIFD, TiffIfd *ifd, uint32_t *offsetToNextIFD) {
01409 int err;
01410
01411 err = fseek(fp, offsetToIFD, SEEK_SET);
01412 if (err != 0) {
01413 std::stringstream errMsg;
01414 errMsg << "Unable to seek to IFD at "<<offsetToIFD << ": "<<strerror(errno);
01415 setError("readIfd", errMsg.str());
01416 fclose(fp); fp = NULL;
01417 return false;
01418 }
01419
01420
01421 int count;
01422 uint16_t ifdEntries;
01423 count = fread(&ifdEntries, sizeof(uint16_t), 1, fp);
01424 if (count != 1) {
01425 std::stringstream errMsg;
01426 errMsg << "Unable to read header for IFD at "<<offsetToIFD;
01427 setError("readIfd", errMsg.str());
01428 fclose(fp); fp = NULL;
01429 return false;
01430 }
01431 ifdEntries = convShort(&ifdEntries);
01432 dprintf(4, "TiffFile::readIfd(): In %s, IFD at 0x%x contains %d entries\n", filename().c_str(), (int)offsetToIFD, (int)ifdEntries);
01433
01434
01435 for (int i=0; i < ifdEntries; i++) {
01436 RawTiffIfdEntry entry;
01437 count = fread(&entry.tag, sizeof(entry.tag), 1, fp);
01438 if (count == 1) {
01439 count = fread(&entry.type, sizeof(entry.type), 1, fp);
01440 }
01441 if (count == 1) {
01442 count = fread(&entry.count, sizeof(entry.count), 1, fp);
01443 }
01444 if (count == 1) {
01445 count = fread(&entry.offset, sizeof(entry.offset), 1, fp);
01446 }
01447 if (count != 1) {
01448 std::stringstream errMsg;
01449 errMsg << "Unable to read IFD entry "<<i <<" for IFD at "<<offsetToIFD;
01450 setError("readIfd", errMsg.str());
01451 fclose(fp); fp = NULL;
01452 return false;
01453 }
01454 entry.tag = convShort(&entry.tag);
01455 entry.type = convShort(&entry.type);
01456 entry.count = convLong(&entry.count);
01457
01458 dprintf(5, "TiffFile::readIfd(): IFD entry %d: Tag: %d (%s), Type: %d, Count: %d, Offset: 0x%x\n",
01459 i, entry.tag, tiffEntryLookup(entry.tag) == NULL ? "Unknown" : tiffEntryLookup(entry.tag)->name, entry.type, entry.count, entry.offset);
01460 ifd->add(entry);
01461 }
01462
01463
01464 if (offsetToNextIFD) {
01465 count = fread(offsetToNextIFD, sizeof(uint32_t), 1, fp);
01466 if (count != 1) {
01467 std::stringstream errMsg;
01468 errMsg << "Unable to read next-IFD offset field for IFD at "<<offsetToIFD;
01469 setError("readIfd", errMsg.str());
01470 fclose(fp); fp = NULL;
01471 return false;
01472 }
01473 *offsetToNextIFD = convLong(offsetToNextIFD);
01474 dprintf(DBG_MINOR, "TiffFile::readIfd(): In file %s, IFD at %x has next-IFD offset field of %x\n",
01475 filename().c_str(), offsetToIFD, *offsetToNextIFD);
01476 }
01477
01478 bool success = readSubIfds(ifd);
01479
01480 return success;
01481 }
01482
01483 bool TiffFile::readSubIfds(TiffIfd *ifd) {
01484
01485 ifd->eraseSubIfds();
01486
01487 bool success;
01488 const TiffIfdEntry *subIfdEntry = ifd->find(TIFF_TAG_SubIFDs);
01489 if (subIfdEntry) {
01490 TagValue val = subIfdEntry->value();
01491 if (!val.valid()) {
01492 setError("readSubIfds", "Unable to read TIFF subIFDs");
01493 fclose(fp); fp = NULL;
01494 return false;
01495 }
01496 std::vector<int> subIfdOffsets;
01497 if (val.type == TagValue::Int) {
01498 subIfdOffsets.push_back(val.asInt());
01499 } else {
01500 subIfdOffsets = val;
01501 }
01502 dprintf(DBG_MINOR, "TiffFile::readSubIfds(): %s: IFD has %d subIFDs\n",
01503 filename().c_str(), subIfdOffsets.size());
01504 for (unsigned int i=0; i < subIfdOffsets.size(); i++) {
01505 TiffIfd *subIfd = ifd->addSubIfd();
01506
01507 success = readIfd(subIfdOffsets[i], subIfd, NULL);
01508 if (!success) {
01509 return false;
01510 }
01511 }
01512 }
01513
01514 return true;
01515 }
01516
01517 uint16_t TiffFile::convShort(void const *src) {
01518 uint16_t s = *(uint16_t const *)src;
01519 if (!littleEndian) { s = (s << 8) || (s >> 8); }
01520 return s;
01521 }
01522
01523 uint32_t TiffFile::convLong(void const *src) {
01524 uint32_t l = *(uint32_t const *)src;
01525 if (!littleEndian) l = ((l & 0x000000FF) << 24) ||
01526 ((l & 0x0000FF00) << 8) ||
01527 ((l & 0x00FF0000) >> 8) ||
01528 ((l & 0xFF000000) >> 24);
01529 return l;
01530 }
01531
01532 float TiffFile::convFloat(void const *src) {
01533 return *reinterpret_cast<float *>(convLong(src));
01534 }
01535
01536 double TiffFile::convDouble(void const *src) {
01537 double d;
01538 if (!littleEndian) {
01539 uint8_t *ptr = reinterpret_cast<uint8_t *>(&d);
01540 for (int i=0; i< 8; i++) {
01541 *(ptr++) = *(((uint8_t const *)src)+7-i);
01542 }
01543 } else {
01544 d = *reinterpret_cast<double const *>(src);
01545 }
01546 return d;
01547 }
01548
01549 bool TiffFile::readByteArray(uint32_t offset, uint32_t count, uint8_t *dest) {
01550 if (!dest) { return false; }
01551
01552 int err = fseek(fp, offset, SEEK_SET);
01553 if (err != 0) {
01554 return false;
01555 }
01556 size_t trueCount = fread(dest, sizeof(uint8_t), count, fp);
01557 if (trueCount != count) { return false; }
01558
01559 return true;
01560 }
01561
01562 bool TiffFile::readShortArray(uint32_t offset, uint32_t count, uint16_t *dest) {
01563 if (!dest) { return false; }
01564
01565 int err = fseek(fp, offset, SEEK_SET);
01566 if (err != 0) {
01567 return false;
01568 }
01569 size_t trueCount = fread(dest, sizeof(uint16_t), count, fp);
01570 if (trueCount != count) { return false; }
01571
01572 if (!littleEndian) {
01573 for (size_t i=0; i < count; i++) {
01574 uint16_t s = dest[i];
01575 dest[i] = (s << 8) || (s >> 8);
01576 }
01577 }
01578 return true;
01579 }
01580
01581 TiffRational TiffFile::convRational(void const *src) {
01582 TiffRational r;
01583 r.numerator = convLong(src);
01584 r.denominator = convLong((unsigned char *)src+4);
01585 return r;
01586 }
01587
01588
01589 }