tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

Common.cpp (40083B)


      1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* This Source Code Form is subject to the terms of the Mozilla Public
      3 * License, v. 2.0. If a copy of the MPL was not distributed with this
      4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      5 
      6 #include "Common.h"
      7 
      8 #include <cstdlib>
      9 
     10 #include "gfxPlatform.h"
     11 
     12 #include "ImageFactory.h"
     13 #include "imgITools.h"
     14 #include "mozilla/Preferences.h"
     15 #include "nsComponentManagerUtils.h"
     16 #include "nsDirectoryServiceDefs.h"
     17 #include "nsIFile.h"
     18 #include "nsIInputStream.h"
     19 #include "nsIProperties.h"
     20 #include "nsNetUtil.h"
     21 #include "mozilla/RefPtr.h"
     22 #include "nsStreamUtils.h"
     23 #include "nsString.h"
     24 
     25 namespace mozilla {
     26 namespace image {
     27 
     28 using namespace gfx;
     29 
     30 using std::vector;
     31 
     32 static bool sImageLibInitialized = false;
     33 
     34 AutoInitializeImageLib::AutoInitializeImageLib() {
     35  if (MOZ_LIKELY(sImageLibInitialized)) {
     36    return;
     37  }
     38 
     39  EXPECT_TRUE(NS_IsMainThread());
     40  sImageLibInitialized = true;
     41 
     42  // Ensure AVIF sequence is enabled to run decoder tests.
     43  nsresult rv = Preferences::SetBool("image.avif.sequence.enabled", true);
     44  EXPECT_TRUE(rv == NS_OK);
     45 
     46 #ifdef MOZ_JXL
     47  // Ensure JXL is enabled to run decoder tests.
     48  rv = Preferences::SetBool("image.jxl.enabled", true);
     49  EXPECT_TRUE(rv == NS_OK);
     50 #endif
     51 
     52  // Ensure that ImageLib services are initialized.
     53  nsCOMPtr<imgITools> imgTools =
     54      do_CreateInstance("@mozilla.org/image/tools;1");
     55  EXPECT_TRUE(imgTools != nullptr);
     56 
     57  // Ensure gfxPlatform is initialized.
     58  gfxPlatform::GetPlatform();
     59 
     60  // Ensure we always color manage images with gtests.
     61  gfxPlatform::SetCMSModeOverride(CMSMode::All);
     62 
     63  // Depending on initialization order, it is possible that our pref changes
     64  // have not taken effect yet because there are pending gfx-related events on
     65  // the main thread.
     66  SpinPendingEvents();
     67 }
     68 
     69 void ImageBenchmarkBase::SetUp() {
     70  nsCOMPtr<nsIInputStream> inputStream = LoadFile(mTestCase.mPath);
     71  ASSERT_TRUE(inputStream != nullptr);
     72 
     73  // Figure out how much data we have.
     74  uint64_t length;
     75  nsresult rv = inputStream->Available(&length);
     76  ASSERT_NS_SUCCEEDED(rv);
     77 
     78  // Write the data into a SourceBuffer.
     79  mSourceBuffer = new SourceBuffer();
     80  mSourceBuffer->ExpectLength(length);
     81  rv = mSourceBuffer->AppendFromInputStream(inputStream, length);
     82  ASSERT_NS_SUCCEEDED(rv);
     83  mSourceBuffer->Complete(NS_OK);
     84 }
     85 
     86 void ImageBenchmarkBase::TearDown() {}
     87 
     88 ///////////////////////////////////////////////////////////////////////////////
     89 // General Helpers
     90 ///////////////////////////////////////////////////////////////////////////////
     91 
     92 // These macros work like gtest's ASSERT_* macros, except that they can be used
     93 // in functions that return values.
     94 #define ASSERT_TRUE_OR_RETURN(e, rv) \
     95  EXPECT_TRUE(e);                    \
     96  if (!(e)) {                        \
     97    return rv;                       \
     98  }
     99 
    100 #define ASSERT_EQ_OR_RETURN(a, b, rv) \
    101  EXPECT_EQ(a, b);                    \
    102  if ((a) != (b)) {                   \
    103    return rv;                        \
    104  }
    105 
    106 #define ASSERT_GE_OR_RETURN(a, b, rv) \
    107  EXPECT_GE(a, b);                    \
    108  if (!((a) >= (b))) {                \
    109    return rv;                        \
    110  }
    111 
    112 #define ASSERT_LE_OR_RETURN(a, b, rv) \
    113  EXPECT_LE(a, b);                    \
    114  if (!((a) <= (b))) {                \
    115    return rv;                        \
    116  }
    117 
    118 #define ASSERT_LT_OR_RETURN(a, b, rv) \
    119  EXPECT_LT(a, b);                    \
    120  if (!((a) < (b))) {                 \
    121    return rv;                        \
    122  }
    123 
    124 void SpinPendingEvents() {
    125  nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
    126  EXPECT_TRUE(mainThread != nullptr);
    127 
    128  bool processed;
    129  do {
    130    processed = false;
    131    nsresult rv = mainThread->ProcessNextEvent(false, &processed);
    132    EXPECT_NS_SUCCEEDED(rv);
    133  } while (processed);
    134 }
    135 
    136 already_AddRefed<nsIInputStream> LoadFile(const char* aRelativePath) {
    137  nsresult rv;
    138 
    139  nsCOMPtr<nsIProperties> dirService =
    140      do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID);
    141  ASSERT_TRUE_OR_RETURN(dirService != nullptr, nullptr);
    142 
    143  // Retrieve the current working directory.
    144  nsCOMPtr<nsIFile> file;
    145  rv = dirService->Get(NS_OS_CURRENT_WORKING_DIR, NS_GET_IID(nsIFile),
    146                       getter_AddRefs(file));
    147  ASSERT_TRUE_OR_RETURN(NS_SUCCEEDED(rv), nullptr);
    148  // Construct the final path by appending the working path to the current
    149  // working directory.
    150  file->AppendNative(nsDependentCString(aRelativePath));
    151 
    152  // Construct an input stream for the requested file.
    153  nsCOMPtr<nsIInputStream> inputStream;
    154  rv = NS_NewLocalFileInputStream(getter_AddRefs(inputStream), file);
    155  ASSERT_TRUE_OR_RETURN(NS_SUCCEEDED(rv), nullptr);
    156 
    157  // Ensure the resulting input stream is buffered.
    158  if (!NS_InputStreamIsBuffered(inputStream)) {
    159    nsCOMPtr<nsIInputStream> bufStream;
    160    rv = NS_NewBufferedInputStream(getter_AddRefs(bufStream),
    161                                   inputStream.forget(), 1024);
    162    ASSERT_TRUE_OR_RETURN(NS_SUCCEEDED(rv), nullptr);
    163    inputStream = bufStream;
    164  }
    165 
    166  return inputStream.forget();
    167 }
    168 
    169 bool IsSolidColor(SourceSurface* aSurface, BGRAColor aColor,
    170                  uint8_t aFuzz /* = 0 */) {
    171  IntSize size = aSurface->GetSize();
    172  return RectIsSolidColor(aSurface, IntRect(0, 0, size.width, size.height),
    173                          aColor, aFuzz);
    174 }
    175 
    176 bool RowsAreSolidColor(SourceSurface* aSurface, int32_t aStartRow,
    177                       int32_t aRowCount, BGRAColor aColor,
    178                       uint8_t aFuzz /* = 0 */) {
    179  IntSize size = aSurface->GetSize();
    180  return RectIsSolidColor(
    181      aSurface, IntRect(0, aStartRow, size.width, aRowCount), aColor, aFuzz);
    182 }
    183 
    184 bool RectIsSolidColor(SourceSurface* aSurface, const IntRect& aRect,
    185                      BGRAColor aColor, uint8_t aFuzz /* = 0 */) {
    186  IntSize surfaceSize = aSurface->GetSize();
    187  IntRect rect =
    188      aRect.Intersect(IntRect(0, 0, surfaceSize.width, surfaceSize.height));
    189 
    190  RefPtr<DataSourceSurface> dataSurface = aSurface->GetDataSurface();
    191  ASSERT_TRUE_OR_RETURN(dataSurface != nullptr, false);
    192 
    193  DataSourceSurface::ScopedMap mapping(dataSurface,
    194                                       DataSourceSurface::MapType::READ);
    195  ASSERT_TRUE_OR_RETURN(mapping.IsMapped(), false);
    196  ASSERT_EQ_OR_RETURN(mapping.GetStride(), surfaceSize.width * 4, false);
    197 
    198  uint8_t* data = mapping.GetData();
    199  ASSERT_TRUE_OR_RETURN(data != nullptr, false);
    200 
    201  BGRAColor pmColor = aColor.Premultiply();
    202  uint32_t expectedPixel = pmColor.AsPixel();
    203 
    204  int32_t rowLength = mapping.GetStride();
    205  for (int32_t row = rect.Y(); row < rect.YMost(); ++row) {
    206    for (int32_t col = rect.X(); col < rect.XMost(); ++col) {
    207      int32_t i = row * rowLength + col * 4;
    208      uint32_t gotPixel = *reinterpret_cast<uint32_t*>(data + i);
    209      if (expectedPixel != gotPixel) {
    210        BGRAColor gotColor = BGRAColor::FromPixel(gotPixel);
    211        if (abs(pmColor.mBlue - gotColor.mBlue) > aFuzz ||
    212            abs(pmColor.mGreen - gotColor.mGreen) > aFuzz ||
    213            abs(pmColor.mRed - gotColor.mRed) > aFuzz ||
    214            abs(pmColor.mAlpha - gotColor.mAlpha) > aFuzz) {
    215          EXPECT_EQ(expectedPixel, gotPixel)
    216              << "Color mismatch for rectangle from " << aRect.TopLeft()
    217              << " to " << aRect.BottomRight() << ": "
    218              << "got rgba(" << static_cast<int>(gotColor.mRed) << ", "
    219              << static_cast<int>(gotColor.mGreen) << ", "
    220              << static_cast<int>(gotColor.mBlue) << ", "
    221              << static_cast<int>(gotColor.mAlpha) << "), "
    222              << "expected rgba(" << static_cast<int>(pmColor.mRed) << ", "
    223              << static_cast<int>(pmColor.mGreen) << ", "
    224              << static_cast<int>(pmColor.mBlue) << ", "
    225              << static_cast<int>(pmColor.mAlpha) << ")";
    226          return false;
    227        }
    228      }
    229    }
    230  }
    231 
    232  return true;
    233 }
    234 
    235 bool RowHasPixels(SourceSurface* aSurface, int32_t aRow,
    236                  const vector<BGRAColor>& aPixels) {
    237  ASSERT_GE_OR_RETURN(aRow, 0, false);
    238 
    239  IntSize surfaceSize = aSurface->GetSize();
    240  ASSERT_EQ_OR_RETURN(aPixels.size(), size_t(surfaceSize.width), false);
    241  ASSERT_LT_OR_RETURN(aRow, surfaceSize.height, false);
    242 
    243  RefPtr<DataSourceSurface> dataSurface = aSurface->GetDataSurface();
    244  ASSERT_TRUE_OR_RETURN(dataSurface, false);
    245 
    246  DataSourceSurface::ScopedMap mapping(dataSurface,
    247                                       DataSourceSurface::MapType::READ);
    248  ASSERT_TRUE_OR_RETURN(mapping.IsMapped(), false);
    249  ASSERT_EQ_OR_RETURN(mapping.GetStride(), surfaceSize.width * 4, false);
    250 
    251  uint8_t* data = mapping.GetData();
    252  ASSERT_TRUE_OR_RETURN(data != nullptr, false);
    253 
    254  int32_t rowLength = mapping.GetStride();
    255  for (int32_t col = 0; col < surfaceSize.width; ++col) {
    256    int32_t i = aRow * rowLength + col * 4;
    257    uint32_t gotPixelData = *reinterpret_cast<uint32_t*>(data + i);
    258    BGRAColor gotPixel = BGRAColor::FromPixel(gotPixelData);
    259    EXPECT_EQ(aPixels[col].mBlue, gotPixel.mBlue);
    260    EXPECT_EQ(aPixels[col].mGreen, gotPixel.mGreen);
    261    EXPECT_EQ(aPixels[col].mRed, gotPixel.mRed);
    262    EXPECT_EQ(aPixels[col].mAlpha, gotPixel.mAlpha);
    263    ASSERT_EQ_OR_RETURN(aPixels[col].AsPixel(), gotPixelData, false);
    264  }
    265 
    266  return true;
    267 }
    268 
    269 ///////////////////////////////////////////////////////////////////////////////
    270 // SurfacePipe Helpers
    271 ///////////////////////////////////////////////////////////////////////////////
    272 
    273 already_AddRefed<Decoder> CreateTrivialDecoder() {
    274  DecoderType decoderType = DecoderFactory::GetDecoderType("image/gif");
    275  auto sourceBuffer = MakeNotNull<RefPtr<SourceBuffer>>();
    276  RefPtr<Decoder> decoder = DecoderFactory::CreateAnonymousDecoder(
    277      decoderType, sourceBuffer, Nothing(), DefaultDecoderFlags(),
    278      DefaultSurfaceFlags());
    279  return decoder.forget();
    280 }
    281 
    282 void AssertCorrectPipelineFinalState(SurfaceFilter* aFilter,
    283                                     const IntRect& aInputSpaceRect,
    284                                     const IntRect& aOutputSpaceRect) {
    285  EXPECT_TRUE(aFilter->IsSurfaceFinished());
    286  Maybe<SurfaceInvalidRect> invalidRect = aFilter->TakeInvalidRect();
    287  EXPECT_TRUE(invalidRect.isSome());
    288  EXPECT_EQ(aInputSpaceRect, invalidRect->mInputSpaceRect.ToUnknownRect());
    289  EXPECT_EQ(aOutputSpaceRect, invalidRect->mOutputSpaceRect.ToUnknownRect());
    290 }
    291 
    292 void CheckGeneratedImage(Decoder* aDecoder, const IntRect& aRect,
    293                         uint8_t aFuzz /* = 0 */) {
    294  RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef();
    295  RefPtr<SourceSurface> surface = currentFrame->GetSourceSurface();
    296  CheckGeneratedSurface(surface, aRect, BGRAColor::Green(),
    297                        BGRAColor::Transparent(), aFuzz);
    298 }
    299 
    300 void CheckGeneratedSurface(SourceSurface* aSurface, const IntRect& aRect,
    301                           const BGRAColor& aInnerColor,
    302                           const BGRAColor& aOuterColor,
    303                           uint8_t aFuzz /* = 0 */) {
    304  const IntSize surfaceSize = aSurface->GetSize();
    305 
    306  // This diagram shows how the surface is divided into regions that the code
    307  // below tests for the correct content. The output rect is the bounds of the
    308  // region labeled 'C'.
    309  //
    310  // +---------------------------+
    311  // |             A             |
    312  // +---------+--------+--------+
    313  // |    B    |   C    |   D    |
    314  // +---------+--------+--------+
    315  // |             E             |
    316  // +---------------------------+
    317 
    318  // Check that the output rect itself is the inner color. (Region 'C'.)
    319  EXPECT_TRUE(RectIsSolidColor(aSurface, aRect, aInnerColor, aFuzz));
    320 
    321  // Check that the area above the output rect is the outer color. (Region 'A'.)
    322  EXPECT_TRUE(RectIsSolidColor(aSurface,
    323                               IntRect(0, 0, surfaceSize.width, aRect.Y()),
    324                               aOuterColor, aFuzz));
    325 
    326  // Check that the area to the left of the output rect is the outer color.
    327  // (Region 'B'.)
    328  EXPECT_TRUE(RectIsSolidColor(aSurface,
    329                               IntRect(0, aRect.Y(), aRect.X(), aRect.YMost()),
    330                               aOuterColor, aFuzz));
    331 
    332  // Check that the area to the right of the output rect is the outer color.
    333  // (Region 'D'.)
    334  const int32_t widthOnRight = surfaceSize.width - aRect.XMost();
    335  EXPECT_TRUE(RectIsSolidColor(
    336      aSurface, IntRect(aRect.XMost(), aRect.Y(), widthOnRight, aRect.YMost()),
    337      aOuterColor, aFuzz));
    338 
    339  // Check that the area below the output rect is the outer color. (Region 'E'.)
    340  const int32_t heightBelow = surfaceSize.height - aRect.YMost();
    341  EXPECT_TRUE(RectIsSolidColor(
    342      aSurface, IntRect(0, aRect.YMost(), surfaceSize.width, heightBelow),
    343      aOuterColor, aFuzz));
    344 }
    345 
    346 void CheckWritePixels(Decoder* aDecoder, SurfaceFilter* aFilter,
    347                      const Maybe<IntRect>& aOutputRect /* = Nothing() */,
    348                      const Maybe<IntRect>& aInputRect /* = Nothing() */,
    349                      const Maybe<IntRect>& aInputWriteRect /* = Nothing() */,
    350                      const Maybe<IntRect>& aOutputWriteRect /* = Nothing() */,
    351                      uint8_t aFuzz /* = 0 */) {
    352  CheckTransformedWritePixels(aDecoder, aFilter, BGRAColor::Green(),
    353                              BGRAColor::Green(), aOutputRect, aInputRect,
    354                              aInputWriteRect, aOutputWriteRect, aFuzz);
    355 }
    356 
    357 void CheckTransformedWritePixels(
    358    Decoder* aDecoder, SurfaceFilter* aFilter, const BGRAColor& aInputColor,
    359    const BGRAColor& aOutputColor,
    360    const Maybe<IntRect>& aOutputRect /* = Nothing() */,
    361    const Maybe<IntRect>& aInputRect /* = Nothing() */,
    362    const Maybe<IntRect>& aInputWriteRect /* = Nothing() */,
    363    const Maybe<IntRect>& aOutputWriteRect /* = Nothing() */,
    364    uint8_t aFuzz /* = 0 */) {
    365  IntRect outputRect = aOutputRect.valueOr(IntRect(0, 0, 100, 100));
    366  IntRect inputRect = aInputRect.valueOr(IntRect(0, 0, 100, 100));
    367  IntRect inputWriteRect = aInputWriteRect.valueOr(inputRect);
    368  IntRect outputWriteRect = aOutputWriteRect.valueOr(outputRect);
    369 
    370  // Fill the image.
    371  int32_t count = 0;
    372  auto result = aFilter->WritePixels<uint32_t>([&] {
    373    ++count;
    374    return AsVariant(aInputColor.AsPixel());
    375  });
    376  EXPECT_EQ(WriteState::FINISHED, result);
    377  EXPECT_EQ(inputWriteRect.Width() * inputWriteRect.Height(), count);
    378 
    379  AssertCorrectPipelineFinalState(aFilter, inputRect, outputRect);
    380 
    381  // Attempt to write more data and make sure nothing changes.
    382  const int32_t oldCount = count;
    383  result = aFilter->WritePixels<uint32_t>([&] {
    384    ++count;
    385    return AsVariant(aInputColor.AsPixel());
    386  });
    387  EXPECT_EQ(oldCount, count);
    388  EXPECT_EQ(WriteState::FINISHED, result);
    389  EXPECT_TRUE(aFilter->IsSurfaceFinished());
    390  Maybe<SurfaceInvalidRect> invalidRect = aFilter->TakeInvalidRect();
    391  EXPECT_TRUE(invalidRect.isNothing());
    392 
    393  // Attempt to advance to the next row and make sure nothing changes.
    394  aFilter->AdvanceRow();
    395  EXPECT_TRUE(aFilter->IsSurfaceFinished());
    396  invalidRect = aFilter->TakeInvalidRect();
    397  EXPECT_TRUE(invalidRect.isNothing());
    398 
    399  // Check that the generated image is correct.
    400  RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef();
    401  RefPtr<SourceSurface> surface = currentFrame->GetSourceSurface();
    402  CheckGeneratedSurface(surface, outputWriteRect, aOutputColor,
    403                        BGRAColor::Transparent(), aFuzz);
    404 }
    405 
    406 ///////////////////////////////////////////////////////////////////////////////
    407 // Test Data
    408 ///////////////////////////////////////////////////////////////////////////////
    409 
    410 ImageTestCase GreenPNGTestCase() {
    411  return ImageTestCase("green.png", "image/png", IntSize(100, 100));
    412 }
    413 
    414 ImageTestCase GreenGIFTestCase() {
    415  return ImageTestCase("green.gif", "image/gif", IntSize(100, 100));
    416 }
    417 
    418 ImageTestCase GreenJPGTestCase() {
    419  return ImageTestCase("green.jpg", "image/jpeg", IntSize(100, 100),
    420                       TEST_CASE_IS_FUZZY);
    421 }
    422 
    423 ImageTestCase GreenBMPTestCase() {
    424  return ImageTestCase("green.bmp", "image/bmp", IntSize(100, 100));
    425 }
    426 
    427 ImageTestCase GreenICOTestCase() {
    428  // This ICO contains a 32-bit BMP, and we use a BMP's alpha data by default
    429  // when the BMP is embedded in an ICO, so it's transparent.
    430  return ImageTestCase("green.ico", "image/x-icon", IntSize(100, 100),
    431                       TEST_CASE_IS_TRANSPARENT);
    432 }
    433 
    434 ImageTestCase GreenIconTestCase() {
    435  return ImageTestCase("green.icon", "image/icon", IntSize(100, 100),
    436                       TEST_CASE_IS_TRANSPARENT);
    437 }
    438 
    439 ImageTestCase GreenWebPTestCase() {
    440  return ImageTestCase("green.webp", "image/webp", IntSize(100, 100));
    441 }
    442 
    443 ImageTestCase GreenAVIFTestCase() {
    444  return ImageTestCase("green.avif", "image/avif", IntSize(100, 100));
    445 }
    446 
    447 ImageTestCase NonzeroReservedAVIFTestCase() {
    448  auto testCase = ImageTestCase("hdlr-nonzero-reserved-bug-1727033.avif",
    449                                "image/avif", IntSize(1, 1));
    450  testCase.mColor = BGRAColor(0x00, 0x00, 0x00, 0xFF);
    451  return testCase;
    452 }
    453 
    454 ImageTestCase MultipleColrAVIFTestCase() {
    455  auto testCase = ImageTestCase("valid-avif-colr-nclx-and-prof.avif",
    456                                "image/avif", IntSize(1, 1));
    457  testCase.mColor = BGRAColor(0x00, 0x00, 0x00, 0xFF);
    458  return testCase;
    459 }
    460 
    461 ImageTestCase Transparent10bit420AVIFTestCase() {
    462  auto testCase =
    463      ImageTestCase("transparent-green-50pct-10bit-yuv420.avif", "image/avif",
    464                    IntSize(100, 100), TEST_CASE_IS_TRANSPARENT);
    465  testCase.mColor = BGRAColor(0x00, 0xFF, 0x00, 0x80);
    466  return testCase;
    467 }
    468 
    469 ImageTestCase Transparent10bit422AVIFTestCase() {
    470  auto testCase =
    471      ImageTestCase("transparent-green-50pct-10bit-yuv422.avif", "image/avif",
    472                    IntSize(100, 100), TEST_CASE_IS_TRANSPARENT);
    473  testCase.mColor = BGRAColor(0x00, 0xFF, 0x00, 0x80);
    474  return testCase;
    475 }
    476 
    477 ImageTestCase Transparent10bit444AVIFTestCase() {
    478  auto testCase =
    479      ImageTestCase("transparent-green-50pct-10bit-yuv444.avif", "image/avif",
    480                    IntSize(100, 100), TEST_CASE_IS_TRANSPARENT);
    481  testCase.mColor = BGRAColor(0x00, 0xFF, 0x00, 0x80);
    482  return testCase;
    483 }
    484 
    485 ImageTestCase Transparent12bit420AVIFTestCase() {
    486  auto testCase =
    487      ImageTestCase("transparent-green-50pct-12bit-yuv420.avif", "image/avif",
    488                    IntSize(100, 100), TEST_CASE_IS_TRANSPARENT);
    489  testCase.mColor = BGRAColor(0x00, 0xFF, 0x00, 0x80);
    490  return testCase;
    491 }
    492 
    493 ImageTestCase Transparent12bit422AVIFTestCase() {
    494  auto testCase =
    495      ImageTestCase("transparent-green-50pct-12bit-yuv422.avif", "image/avif",
    496                    IntSize(100, 100), TEST_CASE_IS_TRANSPARENT);
    497  testCase.mColor = BGRAColor(0x00, 0xFF, 0x00, 0x80);
    498  return testCase;
    499 }
    500 
    501 ImageTestCase Transparent12bit444AVIFTestCase() {
    502  auto testCase =
    503      ImageTestCase("transparent-green-50pct-12bit-yuv444.avif", "image/avif",
    504                    IntSize(100, 100), TEST_CASE_IS_TRANSPARENT);
    505  testCase.mColor = BGRAColor(0x00, 0xFF, 0x00, 0x80);
    506  return testCase;
    507 }
    508 
    509 ImageTestCase Transparent8bit420AVIFTestCase() {
    510  auto testCase =
    511      ImageTestCase("transparent-green-50pct-8bit-yuv420.avif", "image/avif",
    512                    IntSize(100, 100), TEST_CASE_IS_TRANSPARENT);
    513  // Small error is expected
    514  testCase.mColor = BGRAColor(0x02, 0xFF, 0x00, 0x80);
    515  return testCase;
    516 }
    517 
    518 ImageTestCase Transparent8bit422AVIFTestCase() {
    519  auto testCase =
    520      ImageTestCase("transparent-green-50pct-8bit-yuv422.avif", "image/avif",
    521                    IntSize(100, 100), TEST_CASE_IS_TRANSPARENT);
    522  // Small error is expected
    523  testCase.mColor = BGRAColor(0x02, 0xFF, 0x00, 0x80);
    524  return testCase;
    525 }
    526 
    527 ImageTestCase Transparent8bit444AVIFTestCase() {
    528  auto testCase =
    529      ImageTestCase("transparent-green-50pct-8bit-yuv444.avif", "image/avif",
    530                    IntSize(100, 100), TEST_CASE_IS_TRANSPARENT);
    531  // Small error is expected
    532  testCase.mColor = BGRAColor(0x02, 0xFF, 0x00, 0x80);
    533  return testCase;
    534 }
    535 
    536 ImageTestCase Gray8bitLimitedRangeBT601AVIFTestCase() {
    537  auto testCase = ImageTestCase("gray-235-8bit-limited-range-bt601.avif",
    538                                "image/avif", IntSize(100, 100));
    539  testCase.mColor = BGRAColor(0xEB, 0xEB, 0xEB, 0xFF);
    540  return testCase;
    541 }
    542 
    543 ImageTestCase Gray8bitLimitedRangeBT709AVIFTestCase() {
    544  auto testCase = ImageTestCase("gray-235-8bit-limited-range-bt709.avif",
    545                                "image/avif", IntSize(100, 100));
    546  testCase.mColor = BGRAColor(0xEB, 0xEB, 0xEB, 0xFF);
    547  return testCase;
    548 }
    549 
    550 ImageTestCase Gray8bitLimitedRangeBT2020AVIFTestCase() {
    551  auto testCase = ImageTestCase("gray-235-8bit-limited-range-bt2020.avif",
    552                                "image/avif", IntSize(100, 100));
    553  testCase.mColor = BGRAColor(0xEB, 0xEB, 0xEB, 0xFF);
    554  return testCase;
    555 }
    556 
    557 ImageTestCase Gray8bitFullRangeBT601AVIFTestCase() {
    558  auto testCase = ImageTestCase("gray-235-8bit-full-range-bt601.avif",
    559                                "image/avif", IntSize(100, 100));
    560  testCase.mColor = BGRAColor(0xEB, 0xEB, 0xEB, 0xFF);
    561  return testCase;
    562 }
    563 
    564 ImageTestCase Gray8bitFullRangeBT709AVIFTestCase() {
    565  auto testCase = ImageTestCase("gray-235-8bit-full-range-bt709.avif",
    566                                "image/avif", IntSize(100, 100));
    567  testCase.mColor = BGRAColor(0xEB, 0xEB, 0xEB, 0xFF);
    568  return testCase;
    569 }
    570 
    571 ImageTestCase Gray8bitFullRangeBT2020AVIFTestCase() {
    572  auto testCase = ImageTestCase("gray-235-8bit-full-range-bt2020.avif",
    573                                "image/avif", IntSize(100, 100));
    574  testCase.mColor = BGRAColor(0xEB, 0xEB, 0xEB, 0xFF);
    575  return testCase;
    576 }
    577 
    578 ImageTestCase Gray10bitLimitedRangeBT601AVIFTestCase() {
    579  auto testCase = ImageTestCase("gray-235-10bit-limited-range-bt601.avif",
    580                                "image/avif", IntSize(100, 100));
    581  // Small error is expected
    582  testCase.mColor = BGRAColor(0xEA, 0xEA, 0xEA, 0xFF);
    583  return testCase;
    584 }
    585 
    586 ImageTestCase Gray10bitLimitedRangeBT709AVIFTestCase() {
    587  auto testCase = ImageTestCase("gray-235-10bit-limited-range-bt709.avif",
    588                                "image/avif", IntSize(100, 100));
    589  // Small error is expected
    590  testCase.mColor = BGRAColor(0xEA, 0xEA, 0xEA, 0xFF);
    591  return testCase;
    592 }
    593 
    594 ImageTestCase Gray10bitLimitedRangeBT2020AVIFTestCase() {
    595  auto testCase = ImageTestCase("gray-235-10bit-limited-range-bt2020.avif",
    596                                "image/avif", IntSize(100, 100));
    597  // Small error is expected
    598  testCase.mColor = BGRAColor(0xEA, 0xEA, 0xEA, 0xFF);
    599  return testCase;
    600 }
    601 
    602 ImageTestCase Gray10bitFullRangeBT601AVIFTestCase() {
    603  auto testCase = ImageTestCase("gray-235-10bit-full-range-bt601.avif",
    604                                "image/avif", IntSize(100, 100));
    605  testCase.mColor = BGRAColor(0xEB, 0xEB, 0xEB, 0xFF);
    606  return testCase;
    607 }
    608 
    609 ImageTestCase Gray10bitFullRangeBT709AVIFTestCase() {
    610  auto testCase = ImageTestCase("gray-235-10bit-full-range-bt709.avif",
    611                                "image/avif", IntSize(100, 100));
    612  testCase.mColor = BGRAColor(0xEB, 0xEB, 0xEB, 0xFF);
    613  return testCase;
    614 }
    615 
    616 ImageTestCase Gray10bitFullRangeBT2020AVIFTestCase() {
    617  auto testCase = ImageTestCase("gray-235-10bit-full-range-bt2020.avif",
    618                                "image/avif", IntSize(100, 100));
    619  testCase.mColor = BGRAColor(0xEB, 0xEB, 0xEB, 0xFF);
    620  return testCase;
    621 }
    622 
    623 ImageTestCase Gray12bitLimitedRangeBT601AVIFTestCase() {
    624  auto testCase = ImageTestCase("gray-235-12bit-limited-range-bt601.avif",
    625                                "image/avif", IntSize(100, 100));
    626  // Small error is expected
    627  testCase.mColor = BGRAColor(0xEA, 0xEA, 0xEA, 0xFF);
    628  return testCase;
    629 }
    630 
    631 ImageTestCase Gray12bitLimitedRangeBT709AVIFTestCase() {
    632  auto testCase = ImageTestCase("gray-235-12bit-limited-range-bt709.avif",
    633                                "image/avif", IntSize(100, 100));
    634  // Small error is expected
    635  testCase.mColor = BGRAColor(0xEA, 0xEA, 0xEA, 0xFF);
    636  return testCase;
    637 }
    638 
    639 ImageTestCase Gray12bitLimitedRangeBT2020AVIFTestCase() {
    640  auto testCase = ImageTestCase("gray-235-12bit-limited-range-bt2020.avif",
    641                                "image/avif", IntSize(100, 100));
    642  // Small error is expected
    643  testCase.mColor = BGRAColor(0xEA, 0xEA, 0xEA, 0xFF);
    644  return testCase;
    645 }
    646 
    647 ImageTestCase Gray12bitFullRangeBT601AVIFTestCase() {
    648  auto testCase = ImageTestCase("gray-235-12bit-full-range-bt601.avif",
    649                                "image/avif", IntSize(100, 100));
    650  testCase.mColor = BGRAColor(0xEB, 0xEB, 0xEB, 0xFF);
    651  return testCase;
    652 }
    653 
    654 ImageTestCase Gray12bitFullRangeBT709AVIFTestCase() {
    655  auto testCase = ImageTestCase("gray-235-12bit-full-range-bt709.avif",
    656                                "image/avif", IntSize(100, 100));
    657  testCase.mColor = BGRAColor(0xEB, 0xEB, 0xEB, 0xFF);
    658  return testCase;
    659 }
    660 
    661 ImageTestCase Gray12bitFullRangeBT2020AVIFTestCase() {
    662  auto testCase = ImageTestCase("gray-235-12bit-full-range-bt2020.avif",
    663                                "image/avif", IntSize(100, 100));
    664  testCase.mColor = BGRAColor(0xEB, 0xEB, 0xEB, 0xFF);
    665  return testCase;
    666 }
    667 
    668 ImageTestCase Gray8bitLimitedRangeGrayscaleAVIFTestCase() {
    669  auto testCase = ImageTestCase("gray-235-8bit-limited-range-grayscale.avif",
    670                                "image/avif", IntSize(100, 100));
    671  testCase.mColor = BGRAColor(0xEB, 0xEB, 0xEB, 0xFF);
    672  return testCase;
    673 }
    674 
    675 ImageTestCase Gray8bitFullRangeGrayscaleAVIFTestCase() {
    676  auto testCase = ImageTestCase("gray-235-8bit-full-range-grayscale.avif",
    677                                "image/avif", IntSize(100, 100));
    678  testCase.mColor = BGRAColor(0xEB, 0xEB, 0xEB, 0xFF);
    679  return testCase;
    680 }
    681 
    682 ImageTestCase Gray10bitLimitedRangeGrayscaleAVIFTestCase() {
    683  auto testCase = ImageTestCase("gray-235-10bit-limited-range-grayscale.avif",
    684                                "image/avif", IntSize(100, 100));
    685  // Small error is expected
    686  testCase.mColor = BGRAColor(0xEA, 0xEA, 0xEA, 0xFF);
    687  return testCase;
    688 }
    689 
    690 ImageTestCase Gray10bitFullRangeGrayscaleAVIFTestCase() {
    691  auto testCase = ImageTestCase("gray-235-10bit-full-range-grayscale.avif",
    692                                "image/avif", IntSize(100, 100));
    693  testCase.mColor = BGRAColor(0xEB, 0xEB, 0xEB, 0xFF);
    694  return testCase;
    695 }
    696 
    697 ImageTestCase Gray12bitLimitedRangeGrayscaleAVIFTestCase() {
    698  auto testCase = ImageTestCase("gray-235-12bit-limited-range-grayscale.avif",
    699                                "image/avif", IntSize(100, 100));
    700  // Small error is expected
    701  testCase.mColor = BGRAColor(0xEA, 0xEA, 0xEA, 0xFF);
    702  return testCase;
    703 }
    704 
    705 ImageTestCase Gray12bitFullRangeGrayscaleAVIFTestCase() {
    706  auto testCase = ImageTestCase("gray-235-12bit-full-range-grayscale.avif",
    707                                "image/avif", IntSize(100, 100));
    708  testCase.mColor = BGRAColor(0xEB, 0xEB, 0xEB, 0xFF);
    709  return testCase;
    710 }
    711 
    712 ImageTestCase StackCheckAVIFTestCase() {
    713  return ImageTestCase("stackcheck.avif", "image/avif", IntSize(4096, 2924),
    714                       TEST_CASE_IGNORE_OUTPUT);
    715 }
    716 
    717 // Add TEST_CASE_IGNORE_OUTPUT since this isn't a solid green image and we just
    718 // want to test that it decodes correctly.
    719 ImageTestCase MultiLayerAVIFTestCase() {
    720  return ImageTestCase("multilayer.avif", "image/avif", IntSize(1280, 720),
    721                       TEST_CASE_IGNORE_OUTPUT);
    722 }
    723 
    724 ImageTestCase LargeWebPTestCase() {
    725  return ImageTestCase("large.webp", "image/webp", IntSize(1200, 660),
    726                       TEST_CASE_IGNORE_OUTPUT);
    727 }
    728 
    729 ImageTestCase LargeAVIFTestCase() {
    730  return ImageTestCase("large.avif", "image/avif", IntSize(1200, 660),
    731                       TEST_CASE_IGNORE_OUTPUT);
    732 }
    733 
    734 ImageTestCase GreenWebPIccSrgbTestCase() {
    735  return ImageTestCase("green.icc_srgb.webp", "image/webp", IntSize(100, 100));
    736 }
    737 
    738 ImageTestCase GreenFirstFrameAnimatedGIFTestCase() {
    739  return ImageTestCase("first-frame-green.gif", "image/gif", IntSize(100, 100),
    740                       TEST_CASE_IS_ANIMATED, /* aFrameCount */ 2);
    741 }
    742 
    743 ImageTestCase GreenFirstFrameAnimatedPNGTestCase() {
    744  return ImageTestCase("first-frame-green.png", "image/png", IntSize(100, 100),
    745                       TEST_CASE_IS_TRANSPARENT | TEST_CASE_IS_ANIMATED,
    746                       /* aFrameCount */ 2);
    747 }
    748 
    749 ImageTestCase GreenFirstFrameAnimatedWebPTestCase() {
    750  return ImageTestCase("first-frame-green.webp", "image/webp",
    751                       IntSize(100, 100), TEST_CASE_IS_ANIMATED,
    752                       /* aFrameCount */ 2);
    753 }
    754 
    755 ImageTestCase GreenFirstFrameAnimatedAVIFTestCase() {
    756  return ImageTestCase("first-frame-green.avif", "image/avif",
    757                       IntSize(100, 100), TEST_CASE_IS_ANIMATED,
    758                       /* aFrameCount */ 2);
    759 }
    760 
    761 ImageTestCase BlendAnimatedGIFTestCase() {
    762  return ImageTestCase("blend.gif", "image/gif", IntSize(100, 100),
    763                       TEST_CASE_IS_ANIMATED, /* aFrameCount */ 2);
    764 }
    765 
    766 ImageTestCase BlendAnimatedPNGTestCase() {
    767  return ImageTestCase("blend.png", "image/png", IntSize(100, 100),
    768                       TEST_CASE_IS_TRANSPARENT | TEST_CASE_IS_ANIMATED,
    769                       /* aFrameCount */ 2);
    770 }
    771 
    772 ImageTestCase BlendAnimatedWebPTestCase() {
    773  return ImageTestCase("blend.webp", "image/webp", IntSize(100, 100),
    774                       TEST_CASE_IS_TRANSPARENT | TEST_CASE_IS_ANIMATED,
    775                       /* aFrameCount */ 2);
    776 }
    777 
    778 ImageTestCase BlendAnimatedAVIFTestCase() {
    779  return ImageTestCase("blend.avif", "image/avif", IntSize(100, 100),
    780                       TEST_CASE_IS_TRANSPARENT | TEST_CASE_IS_ANIMATED,
    781                       /* aFrameCount */ 2);
    782 }
    783 
    784 ImageTestCase CorruptTestCase() {
    785  return ImageTestCase("corrupt.jpg", "image/jpeg", IntSize(100, 100),
    786                       TEST_CASE_HAS_ERROR);
    787 }
    788 
    789 ImageTestCase CorruptBMPWithTruncatedHeader() {
    790  // This BMP has a header which is truncated right between the BIH and the
    791  // bitfields, which is a particularly error-prone place w.r.t. the BMP decoder
    792  // state machine.
    793  return ImageTestCase("invalid-truncated-metadata.bmp", "image/bmp",
    794                       IntSize(100, 100), TEST_CASE_HAS_ERROR);
    795 }
    796 
    797 ImageTestCase CorruptICOWithBadBMPWidthTestCase() {
    798  // This ICO contains a BMP icon which has a width that doesn't match the size
    799  // listed in the corresponding ICO directory entry.
    800  return ImageTestCase("corrupt-with-bad-bmp-width.ico", "image/x-icon",
    801                       IntSize(100, 100), TEST_CASE_HAS_ERROR);
    802 }
    803 
    804 ImageTestCase CorruptICOWithBadBMPHeightTestCase() {
    805  // This ICO contains a BMP icon which has a height that doesn't match the size
    806  // listed in the corresponding ICO directory entry.
    807  return ImageTestCase("corrupt-with-bad-bmp-height.ico", "image/x-icon",
    808                       IntSize(100, 100), TEST_CASE_HAS_ERROR);
    809 }
    810 
    811 ImageTestCase CorruptICOWithBadBppTestCase() {
    812  // This test case is an ICO with a BPP (15) in the ICO header which differs
    813  // from that in the BMP header itself (1). It should ignore the ICO BPP when
    814  // the BMP BPP is available and thus correctly decode the image.
    815  return ImageTestCase("corrupt-with-bad-ico-bpp.ico", "image/x-icon",
    816                       IntSize(100, 100), TEST_CASE_IS_TRANSPARENT);
    817 }
    818 
    819 ImageTestCase CorruptAVIFTestCase() {
    820  return ImageTestCase("bug-1655846.avif", "image/avif", IntSize(100, 100),
    821                       TEST_CASE_HAS_ERROR);
    822 }
    823 
    824 ImageTestCase TransparentAVIFTestCase() {
    825  return ImageTestCase("transparent.avif", "image/avif", IntSize(1200, 1200),
    826                       TEST_CASE_IS_TRANSPARENT);
    827 }
    828 
    829 ImageTestCase TransparentPNGTestCase() {
    830  return ImageTestCase("transparent.png", "image/png", IntSize(32, 32),
    831                       TEST_CASE_IS_TRANSPARENT);
    832 }
    833 
    834 ImageTestCase TransparentGIFTestCase() {
    835  return ImageTestCase("transparent.gif", "image/gif", IntSize(16, 16),
    836                       TEST_CASE_IS_TRANSPARENT);
    837 }
    838 
    839 ImageTestCase TransparentWebPTestCase() {
    840  ImageTestCase test("transparent.webp", "image/webp", IntSize(100, 100),
    841                     TEST_CASE_IS_TRANSPARENT);
    842  test.mColor = BGRAColor::Transparent();
    843  return test;
    844 }
    845 
    846 ImageTestCase TransparentNoAlphaHeaderWebPTestCase() {
    847  ImageTestCase test("transparent-no-alpha-header.webp", "image/webp",
    848                     IntSize(100, 100), TEST_CASE_IS_FUZZY);
    849  test.mColor = BGRAColor(0x00, 0x00, 0x00, 0xFF);  // black
    850  return test;
    851 }
    852 
    853 ImageTestCase FirstFramePaddingGIFTestCase() {
    854  return ImageTestCase("transparent.gif", "image/gif", IntSize(16, 16),
    855                       TEST_CASE_IS_TRANSPARENT);
    856 }
    857 
    858 ImageTestCase TransparentIfWithinICOBMPTestCase(TestCaseFlags aFlags) {
    859  // This is a BMP that is only transparent when decoded as if it is within an
    860  // ICO file. (Note: aFlags needs to be set to TEST_CASE_DEFAULT_FLAGS or
    861  // TEST_CASE_IS_TRANSPARENT accordingly.)
    862  return ImageTestCase("transparent-if-within-ico.bmp", "image/bmp",
    863                       IntSize(32, 32), aFlags);
    864 }
    865 
    866 ImageTestCase RLE4BMPTestCase() {
    867  return ImageTestCase("rle4.bmp", "image/bmp", IntSize(320, 240),
    868                       TEST_CASE_IS_TRANSPARENT);
    869 }
    870 
    871 ImageTestCase RLE8BMPTestCase() {
    872  return ImageTestCase("rle8.bmp", "image/bmp", IntSize(32, 32),
    873                       TEST_CASE_IS_TRANSPARENT);
    874 }
    875 
    876 ImageTestCase NoFrameDelayGIFTestCase() {
    877  // This is an invalid (or at least, questionably valid) GIF that's animated
    878  // even though it specifies a frame delay of zero. It's animated, but it's not
    879  // marked TEST_CASE_IS_ANIMATED because the metadata decoder can't detect that
    880  // it's animated.
    881  return ImageTestCase("no-frame-delay.gif", "image/gif", IntSize(100, 100));
    882 }
    883 
    884 ImageTestCase ExtraImageSubBlocksAnimatedGIFTestCase() {
    885  // This is a corrupt GIF that has extra image sub blocks between the first and
    886  // second frame.
    887  return ImageTestCase("animated-with-extra-image-sub-blocks.gif", "image/gif",
    888                       IntSize(100, 100));
    889 }
    890 
    891 ImageTestCase DownscaledPNGTestCase() {
    892  // This testcase (and all the other "downscaled") testcases) consists of 25
    893  // lines of green, followed by 25 lines of red, followed by 25 lines of green,
    894  // followed by 25 more lines of red. It's intended that tests downscale it
    895  // from 100x100 to 20x20, so we specify a 20x20 output size.
    896  return ImageTestCase("downscaled.png", "image/png", IntSize(100, 100),
    897                       IntSize(20, 20));
    898 }
    899 
    900 ImageTestCase DownscaledGIFTestCase() {
    901  return ImageTestCase("downscaled.gif", "image/gif", IntSize(100, 100),
    902                       IntSize(20, 20));
    903 }
    904 
    905 ImageTestCase DownscaledJPGTestCase() {
    906  return ImageTestCase("downscaled.jpg", "image/jpeg", IntSize(100, 100),
    907                       IntSize(20, 20));
    908 }
    909 
    910 ImageTestCase DownscaledBMPTestCase() {
    911  return ImageTestCase("downscaled.bmp", "image/bmp", IntSize(100, 100),
    912                       IntSize(20, 20));
    913 }
    914 
    915 ImageTestCase DownscaledICOTestCase() {
    916  return ImageTestCase("downscaled.ico", "image/x-icon", IntSize(100, 100),
    917                       IntSize(20, 20), TEST_CASE_IS_TRANSPARENT);
    918 }
    919 
    920 ImageTestCase DownscaledIconTestCase() {
    921  return ImageTestCase("downscaled.icon", "image/icon", IntSize(100, 100),
    922                       IntSize(20, 20), TEST_CASE_IS_TRANSPARENT);
    923 }
    924 
    925 ImageTestCase DownscaledWebPTestCase() {
    926  return ImageTestCase("downscaled.webp", "image/webp", IntSize(100, 100),
    927                       IntSize(20, 20));
    928 }
    929 
    930 ImageTestCase DownscaledAVIFTestCase() {
    931  return ImageTestCase("downscaled.avif", "image/avif", IntSize(100, 100),
    932                       IntSize(20, 20));
    933 }
    934 
    935 ImageTestCase DownscaledTransparentICOWithANDMaskTestCase() {
    936  // This test case is an ICO with AND mask transparency. We want to ensure that
    937  // we can downscale it without crashing or triggering ASAN failures, but its
    938  // content isn't simple to verify, so for now we don't check the output.
    939  return ImageTestCase("transparent-ico-with-and-mask.ico", "image/x-icon",
    940                       IntSize(32, 32), IntSize(20, 20),
    941                       TEST_CASE_IS_TRANSPARENT | TEST_CASE_IGNORE_OUTPUT);
    942 }
    943 
    944 ImageTestCase TruncatedSmallGIFTestCase() {
    945  return ImageTestCase("green-1x1-truncated.gif", "image/gif", IntSize(1, 1),
    946                       TEST_CASE_IS_TRANSPARENT);
    947 }
    948 
    949 ImageTestCase LargeICOWithBMPTestCase() {
    950  return ImageTestCase("green-large-bmp.ico", "image/x-icon", IntSize(256, 256),
    951                       TEST_CASE_IS_TRANSPARENT);
    952 }
    953 
    954 ImageTestCase LargeICOWithPNGTestCase() {
    955  return ImageTestCase("green-large-png.ico", "image/x-icon", IntSize(512, 512),
    956                       TEST_CASE_IS_TRANSPARENT);
    957 }
    958 
    959 ImageTestCase GreenMultipleSizesICOTestCase() {
    960  return ImageTestCase("green-multiple-sizes.ico", "image/x-icon",
    961                       IntSize(256, 256));
    962 }
    963 
    964 ImageTestCase PerfGrayJPGTestCase() {
    965  return ImageTestCase("perf_gray.jpg", "image/jpeg", IntSize(1000, 1000));
    966 }
    967 
    968 ImageTestCase PerfCmykJPGTestCase() {
    969  return ImageTestCase("perf_cmyk.jpg", "image/jpeg", IntSize(1000, 1000));
    970 }
    971 
    972 ImageTestCase PerfYCbCrJPGTestCase() {
    973  return ImageTestCase("perf_ycbcr.jpg", "image/jpeg", IntSize(1000, 1000));
    974 }
    975 
    976 ImageTestCase PerfRgbPNGTestCase() {
    977  return ImageTestCase("perf_srgb.png", "image/png", IntSize(1000, 1000));
    978 }
    979 
    980 ImageTestCase PerfRgbAlphaPNGTestCase() {
    981  return ImageTestCase("perf_srgb_alpha.png", "image/png", IntSize(1000, 1000),
    982                       TEST_CASE_IS_TRANSPARENT);
    983 }
    984 
    985 ImageTestCase PerfGrayPNGTestCase() {
    986  return ImageTestCase("perf_gray.png", "image/png", IntSize(1000, 1000));
    987 }
    988 
    989 ImageTestCase PerfGrayAlphaPNGTestCase() {
    990  return ImageTestCase("perf_gray_alpha.png", "image/png", IntSize(1000, 1000),
    991                       TEST_CASE_IS_TRANSPARENT);
    992 }
    993 
    994 ImageTestCase PerfRgbLosslessWebPTestCase() {
    995  return ImageTestCase("perf_srgb_lossless.webp", "image/webp",
    996                       IntSize(1000, 1000));
    997 }
    998 
    999 ImageTestCase PerfRgbAlphaLosslessWebPTestCase() {
   1000  return ImageTestCase("perf_srgb_alpha_lossless.webp", "image/webp",
   1001                       IntSize(1000, 1000), TEST_CASE_IS_TRANSPARENT);
   1002 }
   1003 
   1004 ImageTestCase PerfRgbLossyWebPTestCase() {
   1005  return ImageTestCase("perf_srgb_lossy.webp", "image/webp",
   1006                       IntSize(1000, 1000));
   1007 }
   1008 
   1009 ImageTestCase PerfRgbAlphaLossyWebPTestCase() {
   1010  return ImageTestCase("perf_srgb_alpha_lossy.webp", "image/webp",
   1011                       IntSize(1000, 1000), TEST_CASE_IS_TRANSPARENT);
   1012 }
   1013 
   1014 ImageTestCase PerfRgbGIFTestCase() {
   1015  return ImageTestCase("perf_srgb.gif", "image/gif", IntSize(1000, 1000));
   1016 }
   1017 
   1018 #ifdef MOZ_JXL
   1019 ImageTestCase GreenJXLTestCase() {
   1020  return ImageTestCase("green.jxl", "image/jxl", IntSize(100, 100));
   1021 }
   1022 
   1023 ImageTestCase DownscaledJXLTestCase() {
   1024  return ImageTestCase("downscaled.jxl", "image/jxl", IntSize(100, 100),
   1025                       IntSize(20, 20));
   1026 }
   1027 
   1028 ImageTestCase LargeJXLTestCase() {
   1029  return ImageTestCase("large.jxl", "image/jxl", IntSize(1200, 660),
   1030                       TEST_CASE_IGNORE_OUTPUT);
   1031 }
   1032 
   1033 ImageTestCase TransparentJXLTestCase() {
   1034  return ImageTestCase("transparent.jxl", "image/jxl", IntSize(1200, 1200),
   1035                       TEST_CASE_IS_TRANSPARENT);
   1036 }
   1037 #endif
   1038 
   1039 ImageTestCase ExifResolutionTestCase() {
   1040  return ImageTestCase("exif_resolution.jpg", "image/jpeg", IntSize(100, 50));
   1041 }
   1042 
   1043 RefPtr<Image> TestCaseToDecodedImage(const ImageTestCase& aTestCase) {
   1044  RefPtr<Image> image = ImageFactory::CreateAnonymousImage(
   1045      nsDependentCString(aTestCase.mMimeType));
   1046  MOZ_RELEASE_ASSERT(!image->HasError());
   1047 
   1048  nsCOMPtr<nsIInputStream> inputStream = LoadFile(aTestCase.mPath);
   1049  MOZ_RELEASE_ASSERT(inputStream);
   1050 
   1051  // Figure out how much data we have.
   1052  uint64_t length;
   1053  nsresult rv = inputStream->Available(&length);
   1054  MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
   1055 
   1056  // Write the data into the image.
   1057  rv = image->OnImageDataAvailable(nullptr, inputStream, 0,
   1058                                   static_cast<uint32_t>(length));
   1059  MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
   1060 
   1061  // Let the image know we've sent all the data.
   1062  rv = image->OnImageDataComplete(nullptr, NS_OK, true);
   1063  MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
   1064 
   1065  RefPtr<ProgressTracker> tracker = image->GetProgressTracker();
   1066  tracker->SyncNotifyProgress(FLAG_LOAD_COMPLETE);
   1067 
   1068  // Use GetFrame() to force a sync decode of the image.
   1069  RefPtr<SourceSurface> surface = image->GetFrame(
   1070      imgIContainer::FRAME_CURRENT, imgIContainer::FLAG_SYNC_DECODE);
   1071  (void)surface;
   1072  return image;
   1073 }
   1074 
   1075 }  // namespace image
   1076 }  // namespace mozilla