// Copyright (c) the JPEG XL Project Authors. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file.
template <typename T> bool SamePixels(const Plane<T>& image1, const Plane<T>& image2,
std::stringstream& failures) { const Rect rect(image1); if (!SameSize(image1, image2)) {
failures << "size mismatch\n"; returnfalse;
}
size_t mismatches = 0; for (size_t y = rect.y0(); y < rect.ysize(); ++y) { const T* const JXL_RESTRICT row1 = image1.Row(y); const T* const JXL_RESTRICT row2 = image2.Row(y); for (size_t x = rect.x0(); x < rect.xsize(); ++x) { if (row1[x] != row2[x]) {
failures << "pixel mismatch" << x << ", " << y << ": "
<< static_cast<double>(row1[x])
<< " != " << static_cast<double>(row2[x]) << "\n"; if (++mismatches > 4) { returnfalse;
}
}
}
} return mismatches == 0;
}
template <typename T> bool SamePixels(const Image3<T>& image1, const Image3<T>& image2,
std::stringstream& failures) { if (!SameSize(image1, image2)) {
failures << "size mismatch\n"; returnfalse;
} for (size_t c = 0; c < 3; ++c) { if (!SamePixels(image1.Plane(c), image2.Plane(c), failures)) { returnfalse;
}
} returntrue;
}
// Use for floating-point images with fairly large numbers; tolerates small // absolute errors and/or small relative errors. template <typename T> bool VerifyRelativeError(const Plane<T>& expected, const Plane<T>& actual, constdouble threshold_l1, constdouble threshold_relative,
std::stringstream& failures, const intptr_t border = 0, constint c = 0) { if (!SameSize(expected, actual)) {
failures << "size mismatch\n"; returnfalse;
} const intptr_t xsize = expected.xsize(); const intptr_t ysize = expected.ysize();
// Max over current scanline to give a better idea whether there are // systematic errors or just one outlier. Invalid if negative. double max_l1 = -1; double max_relative = -1; bool any_bad = false; for (intptr_t y = border; y < ysize - border; ++y) { const T* const JXL_RESTRICT row_expected = expected.Row(y); const T* const JXL_RESTRICT row_actual = actual.Row(y); for (intptr_t x = border; x < xsize - border; ++x) { constdouble l1 = std::abs(row_expected[x] - row_actual[x]);
// Cannot compute relative, only check/update L1. if (std::abs(row_expected[x]) < 1E-10) { if (l1 > threshold_l1) {
any_bad = true;
max_l1 = std::max(max_l1, l1);
}
} else { constdouble relative =
l1 / std::abs(static_cast<double>(row_expected[x])); if (l1 > threshold_l1 && relative > threshold_relative) { // Fails both tolerances => will exit below, update max_*.
any_bad = true;
max_l1 = std::max(max_l1, l1);
max_relative = std::max(max_relative, relative);
}
}
}
} if (!any_bad) { returntrue;
} // Never had a valid relative value, don't print it. if (max_relative < 0) {
fprintf(stderr, "c=%d: max +/- %E exceeds +/- %.2E\n", c, max_l1,
threshold_l1);
} else {
fprintf(stderr, "c=%d: max +/- %E, x %E exceeds +/- %.2E, x %.2E\n", c,
max_l1, max_relative, threshold_l1, threshold_relative);
} // Dump the expected image and actual image if the region is small enough. const intptr_t kMaxTestDumpSize = 16; if (xsize <= kMaxTestDumpSize + 2 * border &&
ysize <= kMaxTestDumpSize + 2 * border) {
fprintf(stderr, "Expected image:\n"); for (intptr_t y = border; y < ysize - border; ++y) { const T* const JXL_RESTRICT row_expected = expected.Row(y); for (intptr_t x = border; x < xsize - border; ++x) {
fprintf(stderr, "%10lf ", static_cast<double>(row_expected[x]));
}
fprintf(stderr, "\n");
}
fprintf(stderr, "Actual image:\n"); for (intptr_t y = border; y < ysize - border; ++y) { const T* const JXL_RESTRICT row_expected = expected.Row(y); const T* const JXL_RESTRICT row_actual = actual.Row(y); for (intptr_t x = border; x < xsize - border; ++x) { constdouble l1 = std::abs(row_expected[x] - row_actual[x]);
// Find first failing x for further debugging. for (intptr_t y = border; y < ysize - border; ++y) { const T* const JXL_RESTRICT row_expected = expected.Row(y); const T* const JXL_RESTRICT row_actual = actual.Row(y);
for (intptr_t x = border; x < xsize - border; ++x) { constdouble l1 = std::abs(row_expected[x] - row_actual[x]);
bool bad = l1 > threshold_l1; if (row_expected[x] > 1E-10) { constdouble relative =
l1 / std::abs(static_cast<double>(row_expected[x]));
bad &= relative > threshold_relative;
} if (bad) {
failures << x << ", " << y << " (" << expected.xsize() << " x "
<< expected.ysize() << ") expected "
<< static_cast<double>(row_expected[x]) << " actual "
<< static_cast<double>(row_actual[x]); returnfalse;
}
}
} returnfalse;
}
template <typename T> bool VerifyRelativeError(const Image3<T>& expected, const Image3<T>& actual, constfloat threshold_l1, constfloat threshold_relative,
std::stringstream& failures, const intptr_t border = 0) { for (size_t c = 0; c < 3; ++c) { bool ok = VerifyRelativeError(expected.Plane(c), actual.Plane(c),
threshold_l1, threshold_relative, failures,
border, static_cast<int>(c)); if (!ok) { returnfalse;
}
} returntrue;
}
template <typename T, typename U = T> void GenerateImage(Rng& rng, Plane<T>* image, U begin, U end) { for (size_t y = 0; y < image->ysize(); ++y) {
T* const JXL_RESTRICT row = image->Row(y); for (size_t x = 0; x < image->xsize(); ++x) { if (std::is_same<T, float>::value || std::is_same<T, double>::value) {
row[x] = rng.UniformF(begin, end);
} elseif (std::is_signed<T>::value) {
row[x] = rng.UniformI(begin, end);
} else {
row[x] = rng.UniformU(begin, end);
}
}
}
}
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.