bool ImageFileDirectory::IsValidType(uint16_t type) { return type >= 1 && type <= 12; }
size_t ImageFileDirectory::BytesForType(uint16_t type) { switch (type) { case kTypeUnsignedByte: return 1; case kTypeAsciiString: return 1; case kTypeUnsignedShort: return kSizeShort; case kTypeUnsignedLong: return kSizeLong; case kTypeUnsignedRational: return 8; case kTypeSignedByte: return 1; case kTypeUndefined: return 1; case kTypeSignedShort: return kSizeShort; case kTypeSignedLong: return kSizeLong; case kTypeSignedRational: return 8; case kTypeSingleFloat: return 4; case kTypeDoubleFloat: return 8;
} return 0;
}
// Helper function for computing the address of an entry. staticconst uint8_t* get_entry_address(const SkData* data,
uint32_t ifdOffset,
uint16_t entryIndex) { return data->bytes() + // Base address
ifdOffset + // IFD offset
kSizeShort + // IFD number of entries
kSizeEntry * entryIndex; // Entries
}
// Return true if the IFD starting at |ifdOffset| contains valid number of entries (that doesn't // overrun |data|). staticbool validate_ifd(const SkData* data, bool littleEndian,
uint32_t ifdOffset, bool allowTruncated,
uint16_t* outNumEntries,
uint32_t* outNextIfdOffset) { const uint8_t* dataCurrent = data->bytes();
size_t dataSize = data->size();
// Seek to the IFD offset. if (dataSize < ifdOffset) {
SkCodecPrintf("IFD offset is too large.\n"); returnfalse;
}
dataCurrent += ifdOffset;
dataSize -= ifdOffset;
// Read the number of entries. if (dataSize < kSizeShort) {
SkCodecPrintf("Insufficient space to store number of entries.\n"); returnfalse;
}
uint16_t numEntries = get_endian_short(dataCurrent, littleEndian);
dataCurrent += kSizeShort;
dataSize -= kSizeShort;
// Check that there is enough space for all entries. if (dataSize < kSizeEntry * numEntries) {
SkCodecPrintf("Insufficient space (%u) to store all %u entries.\n", static_cast<uint32_t>(data->size()),
numEntries); if (allowTruncated) { // Set the number of entries to the number of entries that can be fully read, and set // the next IFD offset to 0 (indicating that there is no next IFD).
*outNumEntries = dataSize / kSizeEntry;
*outNextIfdOffset = 0; returntrue;
} returnfalse;
}
// Save the number of entries.
*outNumEntries = numEntries;
// Seek past the entries.
dataCurrent += kSizeEntry * numEntries;
dataSize -= kSizeEntry * numEntries;
// Read the next IFD offset. if (dataSize < kSizeLong) {
SkCodecPrintf("Insufficient space to store next IFD offset.\n"); if (allowTruncated) { // Set the next IFD offset to 0 (indicating that there is no next IFD).
*outNextIfdOffset = 0; returntrue;
} returnfalse;
}
// Save the next IFD offset.
*outNextIfdOffset = get_endian_int(dataCurrent, littleEndian); returntrue;
}
bool ImageFileDirectory::ParseHeader(const SkData* data, bool* outLittleEndian,
uint32_t* outIfdOffset) { // Read the endianness (4 bytes) and IFD offset (4 bytes). if (data->size() < 8) {
SkCodecPrintf("Tiff header must be at least 8 bytes.\n"); returnfalse;
} if (!is_valid_endian_marker(data->bytes(), outLittleEndian)) {
SkCodecPrintf("Tiff header had invalid endian marker 0x%x,0x%x,0x%x,0x%x.\n",
data->bytes()[0],
data->bytes()[1],
data->bytes()[2],
data->bytes()[3]); returnfalse;
}
*outIfdOffset = get_endian_int(data->bytes() + 4, *outLittleEndian); returntrue;
}
// If the entry fits in the remaining 4 bytes, use that. const size_t entryDataBytes = BytesForType(type) * count; const uint8_t* entryData = nullptr; if (entryDataBytes <= kSizeLong) {
entryData = entry;
} else { // Otherwise, the next 4 bytes specify an offset where the data can be found. const uint32_t entryDataOffset = get_endian_int(entry, fLittleEndian); if (fData->size() < entryDataOffset || fData->size() - entryDataOffset < entryDataBytes) { returnfalse;
}
entryData = fData->bytes() + entryDataOffset;
}
if (outTag) *outTag = tag; if (outType) *outType = type; if (outCount) *outCount = count; if (outData) *outData = entryData; if (outDataSize) *outDataSize = entryDataBytes; returntrue;
}
sk_sp<SkData> ImageFileDirectory::getEntryUndefinedData(uint16_t entryIndex) const {
uint16_t type = 0;
uint32_t count = 0; const uint8_t* data = nullptr;
size_t size = 0; if (!getEntryRawData(entryIndex, nullptr, &type, &count, &data, &size)) { return nullptr;
} if (type != kTypeUndefined) { return nullptr;
} return SkData::MakeSubset(fData.get(), data - fData->bytes(), size);
}
bool ImageFileDirectory::getEntryValuesGeneric(uint16_t entryIndex,
uint16_t type,
uint32_t count, void* values) const {
uint16_t entryType = 0;
uint32_t entryCount = 0; const uint8_t* entryData = nullptr; if (!getEntryRawData(entryIndex, nullptr, &entryType, &entryCount, &entryData, nullptr)) { returnfalse;
} if (type != entryType) { returnfalse;
} if (count != entryCount) { returnfalse;
} for (uint32_t i = 0; i < count; ++i) { const uint8_t* data = entryData + i * BytesForType(kTypeUnsignedLong); switch (type) { case kTypeUnsignedShort: reinterpret_cast<uint16_t*>(values)[i] = get_endian_short(data, fLittleEndian); break; case kTypeUnsignedLong: reinterpret_cast<uint32_t*>(values)[i] = get_endian_int(data, fLittleEndian); break; case kTypeSignedRational: {
uint32_t numerator = get_endian_int(data, fLittleEndian);
uint32_t denominator = get_endian_int(data + kSizeLong, fLittleEndian); if (denominator == 0) { // The TIFF specification does not indicate a behavior when the denominator is // zero. The behavior of returning zero for a denominator of zero is a // preservation of the behavior introduced in https://crrev.com/767874. reinterpret_cast<float*>(values)[i] = 0;
} else { reinterpret_cast<float*>(values)[i] =
numerator / static_cast<float>(denominator);
} break;
} case kTypeUnsignedRational: {
uint32_t numerator = get_endian_int(data, fLittleEndian);
uint32_t denominator = get_endian_int(data + kSizeLong, fLittleEndian); if (denominator == 0) { // See comments in kTypeSignedRational. reinterpret_cast<float*>(values)[i] = 0.f;
} else { reinterpret_cast<float*>(values)[i] =
numerator / static_cast<float>(denominator);
} break;
} default:
SkCodecPrintf("Unsupported type %u\n", type); returnfalse; break;
}
} returntrue;
}
} // namespace SkTiff
Messung V0.5
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.