blob: 62aa1ef8ad01b91ae7537809bbb5b6c53701d9d7 [file]
/*
* Copyright 2023 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "include/private/SkExif.h"
#include "include/core/SkData.h"
#include "src/codec/SkCodecPriv.h"
#include "src/codec/SkTiffUtility.h"
#include <memory>
#include <utility>
SkExifMetadata::SkExifMetadata(sk_sp<SkData> data) : fData(std::move(data)) {
bool littleEndian = false;
uint32_t ifdOffset = 0;
if (!SkTiffImageFileDirectory::ParseHeader(fData.get(), &littleEndian, &ifdOffset)) {
SkCodecPrintf("Failed to parse Exif header.\n");
return;
}
parseIfd(ifdOffset, littleEndian, /*isRoot=*/true);
}
void SkExifMetadata::parseIfd(uint32_t ifdOffset, bool littleEndian, bool isRoot) {
auto ifd = SkTiffImageFileDirectory::MakeFromOffset(fData, littleEndian, ifdOffset);
if (!ifd) {
SkCodecPrintf("Failed to make IFD\n");
return;
}
for (uint32_t i = 0; i < ifd->getNumEntries(); ++i) {
switch (ifd->getEntryTag(i)) {
case kOriginTag: {
uint16_t value = 0;
if (!fOriginPresent && ifd->getEntryUnsignedShort(i, 1, &value)) {
if (0 < value && value <= kLast_SkEncodedOrigin) {
fOriginValue = static_cast<SkEncodedOrigin>(value);
fOriginPresent = true;
}
}
break;
}
case kSubIFDOffsetTag: {
uint32_t subIfdOffset = 0;
if (isRoot && ifd->getEntryUnsignedLong(i, 1, &subIfdOffset)) {
parseIfd(subIfdOffset, littleEndian, /*isRoot=*/false);
}
break;
}
default:
break;
}
}
}