blob: 565f917b623cbd6dd922f1e2af6def32b279a35c [file] [log] [blame]
/*
* 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/core/SkData.h"
#include "include/private/SkGainmapInfo.h"
#include "src/codec/SkJpegXmp.h"
#include "src/core/SkMD5.h"
#include "tests/Test.h"
#include <iomanip>
#include <iostream>
#include <regex>
#include <sstream>
DEF_TEST(SkJpegXmp_standardXmp, r) {
const char xmpData[] =
"http://ns.adobe.com/xap/1.0/\0"
R"(
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 6.0.0">
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:hdrgm="http://ns.adobe.com/hdr-gain-map/1.0/">
<rdf:Description rdf:about="">
<hdrgm:Version>1.0</hdrgm:Version>
<hdrgm:GainMapMax>3</hdrgm:GainMapMax>
<hdrgm:HDRCapacityMax>4</hdrgm:HDRCapacityMax>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>)";
std::vector<sk_sp<SkData>> app1Params;
app1Params.push_back(SkData::MakeWithoutCopy(xmpData, sizeof(xmpData) - 1));
auto xmp = SkJpegMakeXmp(app1Params);
REPORTER_ASSERT(r, xmp);
SkGainmapInfo info;
REPORTER_ASSERT(r, xmp->getGainmapInfoHDRGM(&info));
REPORTER_ASSERT(r, info.fGainmapRatioMax.fR == 8.f);
REPORTER_ASSERT(r, info.fDisplayRatioHdr == 16.f);
}
DEF_TEST(SkJpegXmp_defaultValues, r) {
const char xmpData[] =
"http://ns.adobe.com/xap/1.0/\0"
R"(
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 6.0.0">
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:hdrgm="http://ns.adobe.com/hdr-gain-map/1.0/">
<rdf:Description rdf:about="" hdrgm:Version="1.0">
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>)";
std::vector<sk_sp<SkData>> app1Params;
app1Params.push_back(SkData::MakeWithoutCopy(xmpData, sizeof(xmpData) - 1));
auto xmp = SkJpegMakeXmp(app1Params);
REPORTER_ASSERT(r, xmp);
SkGainmapInfo info;
REPORTER_ASSERT(r, xmp->getGainmapInfoHDRGM(&info));
REPORTER_ASSERT(r, info.fGainmapRatioMin.fR == 1.f);
REPORTER_ASSERT(r, info.fGainmapRatioMin.fG == 1.f);
REPORTER_ASSERT(r, info.fGainmapRatioMin.fB == 1.f);
REPORTER_ASSERT(r, info.fGainmapRatioMax.fR == 2.f);
REPORTER_ASSERT(r, info.fGainmapRatioMax.fG == 2.f);
REPORTER_ASSERT(r, info.fGainmapRatioMax.fB == 2.f);
REPORTER_ASSERT(r, info.fGainmapGamma.fR == 1.f);
REPORTER_ASSERT(r, info.fGainmapGamma.fG == 1.f);
REPORTER_ASSERT(r, info.fGainmapGamma.fB == 1.f);
REPORTER_ASSERT(r, info.fEpsilonSdr.fR == 1.f / 64.f);
REPORTER_ASSERT(r, info.fEpsilonSdr.fG == 1.f / 64.f);
REPORTER_ASSERT(r, info.fEpsilonSdr.fB == 1.f / 64.f);
REPORTER_ASSERT(r, info.fEpsilonHdr.fG == 1.f / 64.f);
REPORTER_ASSERT(r, info.fEpsilonHdr.fR == 1.f / 64.f);
REPORTER_ASSERT(r, info.fEpsilonHdr.fB == 1.f / 64.f);
REPORTER_ASSERT(r, info.fDisplayRatioSdr == 1.f);
REPORTER_ASSERT(r, info.fDisplayRatioHdr == 2.f);
}
static std::string uint32_to_string(uint32_t v) {
const char c[4] = {static_cast<char>((v >> 24) & 0xff),
static_cast<char>((v >> 16) & 0xff),
static_cast<char>((v >> 8) & 0xff),
static_cast<char>(v & 0xff)};
return std::string(c, 4);
}
static std::string standard_xmp_with_header(const SkMD5::Digest& digest, const std::string& data) {
const std::string guid = digest.toHexString().c_str();
const std::string dataWithGuid = std::regex_replace(data, std::regex("\\$GUID"), guid);
return std::string("http://ns.adobe.com/xap/1.0/") + '\0' + dataWithGuid;
}
static std::string extended_xmp_with_header(const SkMD5::Digest& digest,
uint32_t size,
uint32_t offset,
const std::string& data) {
return std::string("http://ns.adobe.com/xmp/extension/") + '\0' + digest.toHexString().c_str() +
uint32_to_string(size) + uint32_to_string(offset) + data;
}
DEF_TEST(SkJpegXmp_readExtendedXmp, r) {
const std::string standardXmpData = R"(
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 6.0.0">
<rdf:RDF xmlns:xmpNote="http://ns.adobe.com/xmp/note/">
<rdf:Description rdf:about="">
<xmpNote:HasExtendedXMP>$GUID</xmpNote:HasExtendedXMP>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>)";
const std::string extendedXmpData1 = R"(
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 6.0.0">
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:hdrgm="http://ns.adobe.com/hdr-gain-map/1.0/">
<rdf:Description rdf:about="">
<hdrgm:Version>1.0</hdrgm:Version>
<hdrgm:GainMapMax>3</hdrgm:GainMapMax>
<hdrgm:HDRCapacityMax>4</hdrgm:HDRCapacityMax>)";
const std::string extendedXmpData2 = R"(
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>)";
const uint32_t totalExtendedXmpSize = extendedXmpData1.size() + extendedXmpData2.size();
SkMD5 md5;
md5.write(extendedXmpData1.data(), extendedXmpData1.length());
md5.write(extendedXmpData2.data(), extendedXmpData2.length());
const SkMD5::Digest digest = md5.finish();
const std::string standardXmpDataWithHeader = standard_xmp_with_header(digest, standardXmpData);
const uint32_t offset1 = 0;
const std::string extendedXmpData1WithHeader =
extended_xmp_with_header(digest, totalExtendedXmpSize, offset1, extendedXmpData1);
const uint32_t offset2 = extendedXmpData1.size();
const std::string extendedXmpData2WithHeader =
extended_xmp_with_header(digest, totalExtendedXmpSize, offset2, extendedXmpData2);
std::vector<sk_sp<SkData>> app1Params;
app1Params.push_back(SkData::MakeWithoutCopy(standardXmpDataWithHeader.data(),
standardXmpDataWithHeader.length()));
app1Params.push_back(SkData::MakeWithoutCopy(extendedXmpData1WithHeader.data(),
extendedXmpData1WithHeader.length()));
app1Params.push_back(SkData::MakeWithoutCopy(extendedXmpData2WithHeader.data(),
extendedXmpData2WithHeader.length()));
auto xmp = SkJpegMakeXmp(app1Params);
REPORTER_ASSERT(r, xmp);
SkGainmapInfo info;
REPORTER_ASSERT(r, xmp->getGainmapInfoHDRGM(&info));
REPORTER_ASSERT(r, info.fGainmapRatioMax.fR == 8.f);
REPORTER_ASSERT(r, info.fDisplayRatioHdr == 16.f);
}