|
2 | 2 | // SPDX-License-Identifier: BSD-2-Clause |
3 | 3 |
|
4 | 4 | #include <cstring> |
| 5 | +#include <filesystem> |
| 6 | +#include <fstream> |
5 | 7 |
|
6 | 8 | #include "avif/avif.h" |
7 | 9 | #include "avif/avif_cxx.h" |
@@ -376,6 +378,72 @@ INSTANTIATE_TEST_SUITE_P( |
376 | 378 |
|
377 | 379 | //------------------------------------------------------------------------------ |
378 | 380 |
|
| 381 | +TEST(Avif16bitTest, SampleTransformWithOtherBitDepths) { |
| 382 | + if (!testutil::Av1DecoderAvailable()) { |
| 383 | + GTEST_SKIP() << "AV1 Codec unavailable, skip test."; |
| 384 | + } |
| 385 | + |
| 386 | + const std::string file_path = |
| 387 | + std::string(data_path) + "weld_sato_12B_8B_q0.avif"; |
| 388 | + std::vector<uint8_t> encoded_16bit(std::filesystem::file_size(file_path)); |
| 389 | + std::ifstream(file_path, std::ios::binary) |
| 390 | + .read(reinterpret_cast<char*>(encoded_16bit.data()), |
| 391 | + encoded_16bit.size()); |
| 392 | + |
| 393 | + ImagePtr reference(avifImageCreateEmpty()); |
| 394 | + ASSERT_NE(reference, nullptr); |
| 395 | + DecoderPtr decoder_reference(avifDecoderCreate()); |
| 396 | + ASSERT_NE(decoder_reference, nullptr); |
| 397 | + decoder_reference->imageContentToDecode |= |
| 398 | + AVIF_IMAGE_CONTENT_SAMPLE_TRANSFORMS; |
| 399 | + ASSERT_EQ(avifDecoderReadMemory(decoder_reference.get(), reference.get(), |
| 400 | + encoded_16bit.data(), encoded_16bit.size()), |
| 401 | + AVIF_RESULT_OK); |
| 402 | + |
| 403 | + for (uint8_t num_bits = 0; num_bits <= 32; ++num_bits) { |
| 404 | + if (num_bits == reference->depth) { |
| 405 | + continue; |
| 406 | + } |
| 407 | + std::vector<uint8_t> encoded(encoded_16bit); |
| 408 | + // Replace 'pixi' 3-channel 16-bit by another bit depth. |
| 409 | + bool found_subsequence_to_replace = false; |
| 410 | + for (size_t i = 0; i + 4 <= encoded.size(); ++i) { |
| 411 | + if (!std::memcmp(&encoded[i], |
| 412 | + "pixi" // PixelInformationProperty 4CC |
| 413 | + "\0\0\0\0" // version and flags |
| 414 | + "\3" // num_channels |
| 415 | + "\20\20\20" // bits_per_channels (16 is 20 in octal) |
| 416 | + , |
| 417 | + 4 + 4 + 1 + 3)) { |
| 418 | + encoded[i + 9] = encoded[i + 10] = encoded[i + 11] = num_bits; |
| 419 | + found_subsequence_to_replace = true; |
| 420 | + break; |
| 421 | + } |
| 422 | + } |
| 423 | + ASSERT_TRUE(found_subsequence_to_replace); |
| 424 | + |
| 425 | + ImagePtr decoded(avifImageCreateEmpty()); |
| 426 | + ASSERT_NE(decoded, nullptr); |
| 427 | + DecoderPtr decoder(avifDecoderCreate()); |
| 428 | + ASSERT_NE(decoder, nullptr); |
| 429 | + decoder->imageContentToDecode |= AVIF_IMAGE_CONTENT_SAMPLE_TRANSFORMS; |
| 430 | + const avifResult result = avifDecoderReadMemory( |
| 431 | + decoder.get(), decoded.get(), encoded.data(), encoded.size()); |
| 432 | + const avifResult expected_result = |
| 433 | + num_bits == 0 ? AVIF_RESULT_BMFF_PARSE_FAILED |
| 434 | + : num_bits > 16 ? AVIF_RESULT_NOT_IMPLEMENTED |
| 435 | + : AVIF_RESULT_OK; |
| 436 | + ASSERT_EQ(result, expected_result) << "bits_per_channels " << num_bits; |
| 437 | + if (result == AVIF_RESULT_OK) { |
| 438 | + // The output image should be highly distorted because of the pixel value |
| 439 | + // clamping to (1<<num_bits)-1. |
| 440 | + EXPECT_LE(testutil::GetPsnr(*reference, *decoded), 10.0); |
| 441 | + } |
| 442 | + } |
| 443 | +} |
| 444 | + |
| 445 | +//------------------------------------------------------------------------------ |
| 446 | + |
379 | 447 | } // namespace |
380 | 448 | } // namespace avif |
381 | 449 |
|
|
0 commit comments