Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  Common.cpp   Sprache: C

 
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


#include "Common.h"

#include <cstdlib>

#include "gfxPlatform.h"

#include "ImageFactory.h"
#include "imgITools.h"
#include "mozilla/Preferences.h"
#include "nsComponentManagerUtils.h"
#include "nsDirectoryServiceDefs.h"
#include "nsIFile.h"
#include "nsIInputStream.h"
#include "nsIProperties.h"
#include "nsNetUtil.h"
#include "mozilla/RefPtr.h"
#include "nsStreamUtils.h"
#include "nsString.h"

namespace mozilla {
namespace image {

using namespace gfx;

using std::vector;

static bool sImageLibInitialized = false;

AutoInitializeImageLib::AutoInitializeImageLib() {
  if (MOZ_LIKELY(sImageLibInitialized)) {
    return;
  }

  EXPECT_TRUE(NS_IsMainThread());
  sImageLibInitialized = true;

  // Ensure AVIF is enabled to run decoder tests.
  nsresult rv = Preferences::SetBool("image.avif.enabled"true);
  EXPECT_TRUE(rv == NS_OK);
  rv = Preferences::SetBool("image.avif.sequence.enabled"true);
  EXPECT_TRUE(rv == NS_OK);

#ifdef MOZ_JXL
  // Ensure JXL is enabled to run decoder tests.
  rv = Preferences::SetBool("image.jxl.enabled"true);
  EXPECT_TRUE(rv == NS_OK);
#endif

  // Ensure that ImageLib services are initialized.
  nsCOMPtr<imgITools> imgTools =
      do_CreateInstance("@mozilla.org/image/tools;1");
  EXPECT_TRUE(imgTools != nullptr);

  // Ensure gfxPlatform is initialized.
  gfxPlatform::GetPlatform();

  // Ensure we always color manage images with gtests.
  gfxPlatform::SetCMSModeOverride(CMSMode::All);

  // Depending on initialization order, it is possible that our pref changes
  // have not taken effect yet because there are pending gfx-related events on
  // the main thread.
  SpinPendingEvents();
}

void ImageBenchmarkBase::SetUp() {
  nsCOMPtr<nsIInputStream> inputStream = LoadFile(mTestCase.mPath);
  ASSERT_TRUE(inputStream != nullptr);

  // Figure out how much data we have.
  uint64_t length;
  nsresult rv = inputStream->Available(&length);
  ASSERT_NS_SUCCEEDED(rv);

  // Write the data into a SourceBuffer.
  mSourceBuffer = new SourceBuffer();
  mSourceBuffer->ExpectLength(length);
  rv = mSourceBuffer->AppendFromInputStream(inputStream, length);
  ASSERT_NS_SUCCEEDED(rv);
  mSourceBuffer->Complete(NS_OK);
}

void ImageBenchmarkBase::TearDown() {}

///////////////////////////////////////////////////////////////////////////////
// General Helpers
///////////////////////////////////////////////////////////////////////////////

// These macros work like gtest's ASSERT_* macros, except that they can be used
// in functions that return values.
#define ASSERT_TRUE_OR_RETURN(e, rv) \
  EXPECT_TRUE(e);                    \
  if (!(e)) {                        \
    return rv;                       \
  }

#define ASSERT_EQ_OR_RETURN(a, b, rv) \
  EXPECT_EQ(a, b);                    \
  if ((a) != (b)) {                   \
    return rv;                        \
  }

#define ASSERT_GE_OR_RETURN(a, b, rv) \
  EXPECT_GE(a, b);                    \
  if (!((a) >= (b))) {                \
    return rv;                        \
  }

#define ASSERT_LE_OR_RETURN(a, b, rv) \
  EXPECT_LE(a, b);                    \
  if (!((a) <= (b))) {                \
    return rv;                        \
  }

#define ASSERT_LT_OR_RETURN(a, b, rv) \
  EXPECT_LT(a, b);                    \
  if (!((a) < (b))) {                 \
    return rv;                        \
  }

void SpinPendingEvents() {
  nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
  EXPECT_TRUE(mainThread != nullptr);

  bool processed;
  do {
    processed = false;
    nsresult rv = mainThread->ProcessNextEvent(false, &processed);
    EXPECT_NS_SUCCEEDED(rv);
  } while (processed);
}

already_AddRefed<nsIInputStream> LoadFile(const char* aRelativePath) {
  nsresult rv;

  nsCOMPtr<nsIProperties> dirService =
      do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID);
  ASSERT_TRUE_OR_RETURN(dirService != nullptr, nullptr);

  // Retrieve the current working directory.
  nsCOMPtr<nsIFile> file;
  rv = dirService->Get(NS_OS_CURRENT_WORKING_DIR, NS_GET_IID(nsIFile),
                       getter_AddRefs(file));
  ASSERT_TRUE_OR_RETURN(NS_SUCCEEDED(rv), nullptr);
  // Construct the final path by appending the working path to the current
  // working directory.
  file->AppendNative(nsDependentCString(aRelativePath));

  // Construct an input stream for the requested file.
  nsCOMPtr<nsIInputStream> inputStream;
  rv = NS_NewLocalFileInputStream(getter_AddRefs(inputStream), file);
  ASSERT_TRUE_OR_RETURN(NS_SUCCEEDED(rv), nullptr);

  // Ensure the resulting input stream is buffered.
  if (!NS_InputStreamIsBuffered(inputStream)) {
    nsCOMPtr<nsIInputStream> bufStream;
    rv = NS_NewBufferedInputStream(getter_AddRefs(bufStream),
                                   inputStream.forget(), 1024);
    ASSERT_TRUE_OR_RETURN(NS_SUCCEEDED(rv), nullptr);
    inputStream = bufStream;
  }

  return inputStream.forget();
}

bool IsSolidColor(SourceSurface* aSurface, BGRAColor aColor,
                  uint8_t aFuzz /* = 0 */) {
  IntSize size = aSurface->GetSize();
  return RectIsSolidColor(aSurface, IntRect(0, 0, size.width, size.height),
                          aColor, aFuzz);
}

bool RowsAreSolidColor(SourceSurface* aSurface, int32_t aStartRow,
                       int32_t aRowCount, BGRAColor aColor,
                       uint8_t aFuzz /* = 0 */) {
  IntSize size = aSurface->GetSize();
  return RectIsSolidColor(
      aSurface, IntRect(0, aStartRow, size.width, aRowCount), aColor, aFuzz);
}

bool RectIsSolidColor(SourceSurface* aSurface, const IntRect& aRect,
                      BGRAColor aColor, uint8_t aFuzz /* = 0 */) {
  IntSize surfaceSize = aSurface->GetSize();
  IntRect rect =
      aRect.Intersect(IntRect(0, 0, surfaceSize.width, surfaceSize.height));

  RefPtr<DataSourceSurface> dataSurface = aSurface->GetDataSurface();
  ASSERT_TRUE_OR_RETURN(dataSurface != nullptr, false);

  DataSourceSurface::ScopedMap mapping(dataSurface,
                                       DataSourceSurface::MapType::READ);
  ASSERT_TRUE_OR_RETURN(mapping.IsMapped(), false);
  ASSERT_EQ_OR_RETURN(mapping.GetStride(), surfaceSize.width * 4, false);

  uint8_t* data = mapping.GetData();
  ASSERT_TRUE_OR_RETURN(data != nullptr, false);

  BGRAColor pmColor = aColor.Premultiply();
  uint32_t expectedPixel = pmColor.AsPixel();

  int32_t rowLength = mapping.GetStride();
  for (int32_t row = rect.Y(); row < rect.YMost(); ++row) {
    for (int32_t col = rect.X(); col < rect.XMost(); ++col) {
      int32_t i = row * rowLength + col * 4;
      uint32_t gotPixel = *reinterpret_cast<uint32_t*>(data + i);
      if (expectedPixel != gotPixel) {
        BGRAColor gotColor = BGRAColor::FromPixel(gotPixel);
        if (abs(pmColor.mBlue - gotColor.mBlue) > aFuzz ||
            abs(pmColor.mGreen - gotColor.mGreen) > aFuzz ||
            abs(pmColor.mRed - gotColor.mRed) > aFuzz ||
            abs(pmColor.mAlpha - gotColor.mAlpha) > aFuzz) {
          EXPECT_EQ(expectedPixel, gotPixel)
              << "Color mismatch for rectangle from " << aRect.TopLeft()
              << " to " << aRect.BottomRight() << ": "
              << "got rgba(" << static_cast<int>(gotColor.mRed) << ", "
              << static_cast<int>(gotColor.mGreen) << ", "
              << static_cast<int>(gotColor.mBlue) << ", "
              << static_cast<int>(gotColor.mAlpha) << "), "
              << "expected rgba(" << static_cast<int>(pmColor.mRed) << ", "
              << static_cast<int>(pmColor.mGreen) << ", "
              << static_cast<int>(pmColor.mBlue) << ", "
              << static_cast<int>(pmColor.mAlpha) << ")";
          return false;
        }
      }
    }
  }

  return true;
}

bool RowHasPixels(SourceSurface* aSurface, int32_t aRow,
                  const vector<BGRAColor>& aPixels) {
  ASSERT_GE_OR_RETURN(aRow, 0, false);

  IntSize surfaceSize = aSurface->GetSize();
  ASSERT_EQ_OR_RETURN(aPixels.size(), size_t(surfaceSize.width), false);
  ASSERT_LT_OR_RETURN(aRow, surfaceSize.height, false);

  RefPtr<DataSourceSurface> dataSurface = aSurface->GetDataSurface();
  ASSERT_TRUE_OR_RETURN(dataSurface, false);

  DataSourceSurface::ScopedMap mapping(dataSurface,
                                       DataSourceSurface::MapType::READ);
  ASSERT_TRUE_OR_RETURN(mapping.IsMapped(), false);
  ASSERT_EQ_OR_RETURN(mapping.GetStride(), surfaceSize.width * 4, false);

  uint8_t* data = mapping.GetData();
  ASSERT_TRUE_OR_RETURN(data != nullptr, false);

  int32_t rowLength = mapping.GetStride();
  for (int32_t col = 0; col < surfaceSize.width; ++col) {
    int32_t i = aRow * rowLength + col * 4;
    uint32_t gotPixelData = *reinterpret_cast<uint32_t*>(data + i);
    BGRAColor gotPixel = BGRAColor::FromPixel(gotPixelData);
    EXPECT_EQ(aPixels[col].mBlue, gotPixel.mBlue);
    EXPECT_EQ(aPixels[col].mGreen, gotPixel.mGreen);
    EXPECT_EQ(aPixels[col].mRed, gotPixel.mRed);
    EXPECT_EQ(aPixels[col].mAlpha, gotPixel.mAlpha);
    ASSERT_EQ_OR_RETURN(aPixels[col].AsPixel(), gotPixelData, false);
  }

  return true;
}

///////////////////////////////////////////////////////////////////////////////
// SurfacePipe Helpers
///////////////////////////////////////////////////////////////////////////////

already_AddRefed<Decoder> CreateTrivialDecoder() {
  DecoderType decoderType = DecoderFactory::GetDecoderType("image/gif");
  auto sourceBuffer = MakeNotNull<RefPtr<SourceBuffer>>();
  RefPtr<Decoder> decoder = DecoderFactory::CreateAnonymousDecoder(
      decoderType, sourceBuffer, Nothing(), DefaultDecoderFlags(),
      DefaultSurfaceFlags());
  return decoder.forget();
}

void AssertCorrectPipelineFinalState(SurfaceFilter* aFilter,
                                     const IntRect& aInputSpaceRect,
                                     const IntRect& aOutputSpaceRect) {
  EXPECT_TRUE(aFilter->IsSurfaceFinished());
  Maybe<SurfaceInvalidRect> invalidRect = aFilter->TakeInvalidRect();
  EXPECT_TRUE(invalidRect.isSome());
  EXPECT_EQ(aInputSpaceRect, invalidRect->mInputSpaceRect.ToUnknownRect());
  EXPECT_EQ(aOutputSpaceRect, invalidRect->mOutputSpaceRect.ToUnknownRect());
}

void CheckGeneratedImage(Decoder* aDecoder, const IntRect& aRect,
                         uint8_t aFuzz /* = 0 */) {
  RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef();
  RefPtr<SourceSurface> surface = currentFrame->GetSourceSurface();
  CheckGeneratedSurface(surface, aRect, BGRAColor::Green(),
                        BGRAColor::Transparent(), aFuzz);
}

void CheckGeneratedSurface(SourceSurface* aSurface, const IntRect& aRect,
                           const BGRAColor& aInnerColor,
                           const BGRAColor& aOuterColor,
                           uint8_t aFuzz /* = 0 */) {
  const IntSize surfaceSize = aSurface->GetSize();

  // This diagram shows how the surface is divided into regions that the code
  // below tests for the correct content. The output rect is the bounds of the
  // region labeled 'C'.
  //
  // +---------------------------+
  // |             A             |
  // +---------+--------+--------+
  // |    B    |   C    |   D    |
  // +---------+--------+--------+
  // |             E             |
  // +---------------------------+

  // Check that the output rect itself is the inner color. (Region 'C'.)
  EXPECT_TRUE(RectIsSolidColor(aSurface, aRect, aInnerColor, aFuzz));

  // Check that the area above the output rect is the outer color. (Region 'A'.)
  EXPECT_TRUE(RectIsSolidColor(aSurface,
                               IntRect(0, 0, surfaceSize.width, aRect.Y()),
                               aOuterColor, aFuzz));

  // Check that the area to the left of the output rect is the outer color.
  // (Region 'B'.)
  EXPECT_TRUE(RectIsSolidColor(aSurface,
                               IntRect(0, aRect.Y(), aRect.X(), aRect.YMost()),
                               aOuterColor, aFuzz));

  // Check that the area to the right of the output rect is the outer color.
  // (Region 'D'.)
  const int32_t widthOnRight = surfaceSize.width - aRect.XMost();
  EXPECT_TRUE(RectIsSolidColor(
      aSurface, IntRect(aRect.XMost(), aRect.Y(), widthOnRight, aRect.YMost()),
      aOuterColor, aFuzz));

  // Check that the area below the output rect is the outer color. (Region 'E'.)
  const int32_t heightBelow = surfaceSize.height - aRect.YMost();
  EXPECT_TRUE(RectIsSolidColor(
      aSurface, IntRect(0, aRect.YMost(), surfaceSize.width, heightBelow),
      aOuterColor, aFuzz));
}

void CheckWritePixels(Decoder* aDecoder, SurfaceFilter* aFilter,
                      const Maybe<IntRect>& aOutputRect /* = Nothing() */,
                      const Maybe<IntRect>& aInputRect /* = Nothing() */,
                      const Maybe<IntRect>& aInputWriteRect /* = Nothing() */,
                      const Maybe<IntRect>& aOutputWriteRect /* = Nothing() */,
                      uint8_t aFuzz /* = 0 */) {
  CheckTransformedWritePixels(aDecoder, aFilter, BGRAColor::Green(),
                              BGRAColor::Green(), aOutputRect, aInputRect,
                              aInputWriteRect, aOutputWriteRect, aFuzz);
}

void CheckTransformedWritePixels(
    Decoder* aDecoder, SurfaceFilter* aFilter, const BGRAColor& aInputColor,
    const BGRAColor& aOutputColor,
    const Maybe<IntRect>& aOutputRect /* = Nothing() */,
    const Maybe<IntRect>& aInputRect /* = Nothing() */,
    const Maybe<IntRect>& aInputWriteRect /* = Nothing() */,
    const Maybe<IntRect>& aOutputWriteRect /* = Nothing() */,
    uint8_t aFuzz /* = 0 */) {
  IntRect outputRect = aOutputRect.valueOr(IntRect(0, 0, 100, 100));
  IntRect inputRect = aInputRect.valueOr(IntRect(0, 0, 100, 100));
  IntRect inputWriteRect = aInputWriteRect.valueOr(inputRect);
  IntRect outputWriteRect = aOutputWriteRect.valueOr(outputRect);

  // Fill the image.
  int32_t count = 0;
  auto result = aFilter->WritePixels<uint32_t>([&] {
    ++count;
    return AsVariant(aInputColor.AsPixel());
  });
  EXPECT_EQ(WriteState::FINISHED, result);
  EXPECT_EQ(inputWriteRect.Width() * inputWriteRect.Height(), count);

  AssertCorrectPipelineFinalState(aFilter, inputRect, outputRect);

  // Attempt to write more data and make sure nothing changes.
  const int32_t oldCount = count;
  result = aFilter->WritePixels<uint32_t>([&] {
    ++count;
    return AsVariant(aInputColor.AsPixel());
  });
  EXPECT_EQ(oldCount, count);
  EXPECT_EQ(WriteState::FINISHED, result);
  EXPECT_TRUE(aFilter->IsSurfaceFinished());
  Maybe<SurfaceInvalidRect> invalidRect = aFilter->TakeInvalidRect();
  EXPECT_TRUE(invalidRect.isNothing());

  // Attempt to advance to the next row and make sure nothing changes.
  aFilter->AdvanceRow();
  EXPECT_TRUE(aFilter->IsSurfaceFinished());
  invalidRect = aFilter->TakeInvalidRect();
  EXPECT_TRUE(invalidRect.isNothing());

  // Check that the generated image is correct.
  RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef();
  RefPtr<SourceSurface> surface = currentFrame->GetSourceSurface();
  CheckGeneratedSurface(surface, outputWriteRect, aOutputColor,
                        BGRAColor::Transparent(), aFuzz);
}

///////////////////////////////////////////////////////////////////////////////
// Test Data
///////////////////////////////////////////////////////////////////////////////

ImageTestCase GreenPNGTestCase() {
  return ImageTestCase("green.png""image/png", IntSize(100, 100));
}

ImageTestCase GreenGIFTestCase() {
  return ImageTestCase("green.gif""image/gif", IntSize(100, 100));
}

ImageTestCase GreenJPGTestCase() {
  return ImageTestCase("green.jpg""image/jpeg", IntSize(100, 100),
                       TEST_CASE_IS_FUZZY);
}

ImageTestCase GreenBMPTestCase() {
  return ImageTestCase("green.bmp""image/bmp", IntSize(100, 100));
}

ImageTestCase GreenICOTestCase() {
  // This ICO contains a 32-bit BMP, and we use a BMP's alpha data by default
  // when the BMP is embedded in an ICO, so it's transparent.
  return ImageTestCase("green.ico""image/x-icon", IntSize(100, 100),
                       TEST_CASE_IS_TRANSPARENT);
}

ImageTestCase GreenIconTestCase() {
  return ImageTestCase("green.icon""image/icon", IntSize(100, 100),
                       TEST_CASE_IS_TRANSPARENT);
}

ImageTestCase GreenWebPTestCase() {
  return ImageTestCase("green.webp""image/webp", IntSize(100, 100));
}

ImageTestCase GreenAVIFTestCase() {
  return ImageTestCase("green.avif""image/avif", IntSize(100, 100));
}

ImageTestCase NonzeroReservedAVIFTestCase() {
  auto testCase = ImageTestCase("hdlr-nonzero-reserved-bug-1727033.avif",
                                "image/avif", IntSize(1, 1));
  testCase.mColor = BGRAColor(0x00, 0x00, 0x00, 0xFF);
  return testCase;
}

ImageTestCase MultipleColrAVIFTestCase() {
  auto testCase = ImageTestCase("valid-avif-colr-nclx-and-prof.avif",
                                "image/avif", IntSize(1, 1));
  testCase.mColor = BGRAColor(0x00, 0x00, 0x00, 0xFF);
  return testCase;
}

ImageTestCase Transparent10bit420AVIFTestCase() {
  auto testCase =
      ImageTestCase("transparent-green-50pct-10bit-yuv420.avif""image/avif",
                    IntSize(100, 100), TEST_CASE_IS_TRANSPARENT);
  testCase.mColor = BGRAColor(0x00, 0xFF, 0x00, 0x80);
  return testCase;
}

ImageTestCase Transparent10bit422AVIFTestCase() {
  auto testCase =
      ImageTestCase("transparent-green-50pct-10bit-yuv422.avif""image/avif",
                    IntSize(100, 100), TEST_CASE_IS_TRANSPARENT);
  testCase.mColor = BGRAColor(0x00, 0xFF, 0x00, 0x80);
  return testCase;
}

ImageTestCase Transparent10bit444AVIFTestCase() {
  auto testCase =
      ImageTestCase("transparent-green-50pct-10bit-yuv444.avif""image/avif",
                    IntSize(100, 100), TEST_CASE_IS_TRANSPARENT);
  testCase.mColor = BGRAColor(0x00, 0xFF, 0x00, 0x80);
  return testCase;
}

ImageTestCase Transparent12bit420AVIFTestCase() {
  auto testCase =
      ImageTestCase("transparent-green-50pct-12bit-yuv420.avif""image/avif",
                    IntSize(100, 100), TEST_CASE_IS_TRANSPARENT);
  testCase.mColor = BGRAColor(0x00, 0xFF, 0x00, 0x80);
  return testCase;
}

ImageTestCase Transparent12bit422AVIFTestCase() {
  auto testCase =
      ImageTestCase("transparent-green-50pct-12bit-yuv422.avif""image/avif",
                    IntSize(100, 100), TEST_CASE_IS_TRANSPARENT);
  testCase.mColor = BGRAColor(0x00, 0xFF, 0x00, 0x80);
  return testCase;
}

ImageTestCase Transparent12bit444AVIFTestCase() {
  auto testCase =
      ImageTestCase("transparent-green-50pct-12bit-yuv444.avif""image/avif",
                    IntSize(100, 100), TEST_CASE_IS_TRANSPARENT);
  testCase.mColor = BGRAColor(0x00, 0xFF, 0x00, 0x80);
  return testCase;
}

ImageTestCase Transparent8bit420AVIFTestCase() {
  auto testCase =
      ImageTestCase("transparent-green-50pct-8bit-yuv420.avif""image/avif",
                    IntSize(100, 100), TEST_CASE_IS_TRANSPARENT);
  // Small error is expected
  testCase.mColor = BGRAColor(0x02, 0xFF, 0x00, 0x80);
  return testCase;
}

ImageTestCase Transparent8bit422AVIFTestCase() {
  auto testCase =
      ImageTestCase("transparent-green-50pct-8bit-yuv422.avif""image/avif",
                    IntSize(100, 100), TEST_CASE_IS_TRANSPARENT);
  // Small error is expected
  testCase.mColor = BGRAColor(0x02, 0xFF, 0x00, 0x80);
  return testCase;
}

ImageTestCase Transparent8bit444AVIFTestCase() {
  auto testCase =
      ImageTestCase("transparent-green-50pct-8bit-yuv444.avif""image/avif",
                    IntSize(100, 100), TEST_CASE_IS_TRANSPARENT);
  // Small error is expected
  testCase.mColor = BGRAColor(0x02, 0xFF, 0x00, 0x80);
  return testCase;
}

ImageTestCase Gray8bitLimitedRangeBT601AVIFTestCase() {
  auto testCase = ImageTestCase("gray-235-8bit-limited-range-bt601.avif",
                                "image/avif", IntSize(100, 100));
  testCase.mColor = BGRAColor(0xEB, 0xEB, 0xEB, 0xFF);
  return testCase;
}

ImageTestCase Gray8bitLimitedRangeBT709AVIFTestCase() {
  auto testCase = ImageTestCase("gray-235-8bit-limited-range-bt709.avif",
                                "image/avif", IntSize(100, 100));
  testCase.mColor = BGRAColor(0xEB, 0xEB, 0xEB, 0xFF);
  return testCase;
}

ImageTestCase Gray8bitLimitedRangeBT2020AVIFTestCase() {
  auto testCase = ImageTestCase("gray-235-8bit-limited-range-bt2020.avif",
                                "image/avif", IntSize(100, 100));
  testCase.mColor = BGRAColor(0xEB, 0xEB, 0xEB, 0xFF);
  return testCase;
}

ImageTestCase Gray8bitFullRangeBT601AVIFTestCase() {
  auto testCase = ImageTestCase("gray-235-8bit-full-range-bt601.avif",
                                "image/avif", IntSize(100, 100));
  testCase.mColor = BGRAColor(0xEB, 0xEB, 0xEB, 0xFF);
  return testCase;
}

ImageTestCase Gray8bitFullRangeBT709AVIFTestCase() {
  auto testCase = ImageTestCase("gray-235-8bit-full-range-bt709.avif",
                                "image/avif", IntSize(100, 100));
  testCase.mColor = BGRAColor(0xEB, 0xEB, 0xEB, 0xFF);
  return testCase;
}

ImageTestCase Gray8bitFullRangeBT2020AVIFTestCase() {
  auto testCase = ImageTestCase("gray-235-8bit-full-range-bt2020.avif",
                                "image/avif", IntSize(100, 100));
  testCase.mColor = BGRAColor(0xEB, 0xEB, 0xEB, 0xFF);
  return testCase;
}

ImageTestCase Gray10bitLimitedRangeBT601AVIFTestCase() {
  auto testCase = ImageTestCase("gray-235-10bit-limited-range-bt601.avif",
                                "image/avif", IntSize(100, 100));
  // Small error is expected
  testCase.mColor = BGRAColor(0xEA, 0xEA, 0xEA, 0xFF);
  return testCase;
}

ImageTestCase Gray10bitLimitedRangeBT709AVIFTestCase() {
  auto testCase = ImageTestCase("gray-235-10bit-limited-range-bt709.avif",
                                "image/avif", IntSize(100, 100));
  // Small error is expected
  testCase.mColor = BGRAColor(0xEA, 0xEA, 0xEA, 0xFF);
  return testCase;
}

ImageTestCase Gray10bitLimitedRangeBT2020AVIFTestCase() {
  auto testCase = ImageTestCase("gray-235-10bit-limited-range-bt2020.avif",
                                "image/avif", IntSize(100, 100));
  // Small error is expected
  testCase.mColor = BGRAColor(0xEA, 0xEA, 0xEA, 0xFF);
  return testCase;
}

ImageTestCase Gray10bitFullRangeBT601AVIFTestCase() {
  auto testCase = ImageTestCase("gray-235-10bit-full-range-bt601.avif",
                                "image/avif", IntSize(100, 100));
  testCase.mColor = BGRAColor(0xEB, 0xEB, 0xEB, 0xFF);
  return testCase;
}

ImageTestCase Gray10bitFullRangeBT709AVIFTestCase() {
  auto testCase = ImageTestCase("gray-235-10bit-full-range-bt709.avif",
                                "image/avif", IntSize(100, 100));
  testCase.mColor = BGRAColor(0xEB, 0xEB, 0xEB, 0xFF);
  return testCase;
}

ImageTestCase Gray10bitFullRangeBT2020AVIFTestCase() {
  auto testCase = ImageTestCase("gray-235-10bit-full-range-bt2020.avif",
                                "image/avif", IntSize(100, 100));
  testCase.mColor = BGRAColor(0xEB, 0xEB, 0xEB, 0xFF);
  return testCase;
}

ImageTestCase Gray12bitLimitedRangeBT601AVIFTestCase() {
  auto testCase = ImageTestCase("gray-235-12bit-limited-range-bt601.avif",
                                "image/avif", IntSize(100, 100));
  // Small error is expected
  testCase.mColor = BGRAColor(0xEA, 0xEA, 0xEA, 0xFF);
  return testCase;
}

ImageTestCase Gray12bitLimitedRangeBT709AVIFTestCase() {
  auto testCase = ImageTestCase("gray-235-12bit-limited-range-bt709.avif",
                                "image/avif", IntSize(100, 100));
  // Small error is expected
  testCase.mColor = BGRAColor(0xEA, 0xEA, 0xEA, 0xFF);
  return testCase;
}

ImageTestCase Gray12bitLimitedRangeBT2020AVIFTestCase() {
  auto testCase = ImageTestCase("gray-235-12bit-limited-range-bt2020.avif",
                                "image/avif", IntSize(100, 100));
  // Small error is expected
  testCase.mColor = BGRAColor(0xEA, 0xEA, 0xEA, 0xFF);
  return testCase;
}

ImageTestCase Gray12bitFullRangeBT601AVIFTestCase() {
  auto testCase = ImageTestCase("gray-235-12bit-full-range-bt601.avif",
                                "image/avif", IntSize(100, 100));
  testCase.mColor = BGRAColor(0xEB, 0xEB, 0xEB, 0xFF);
  return testCase;
}

ImageTestCase Gray12bitFullRangeBT709AVIFTestCase() {
  auto testCase = ImageTestCase("gray-235-12bit-full-range-bt709.avif",
                                "image/avif", IntSize(100, 100));
  testCase.mColor = BGRAColor(0xEB, 0xEB, 0xEB, 0xFF);
  return testCase;
}

ImageTestCase Gray12bitFullRangeBT2020AVIFTestCase() {
  auto testCase = ImageTestCase("gray-235-12bit-full-range-bt2020.avif",
                                "image/avif", IntSize(100, 100));
  testCase.mColor = BGRAColor(0xEB, 0xEB, 0xEB, 0xFF);
  return testCase;
}

ImageTestCase Gray8bitLimitedRangeGrayscaleAVIFTestCase() {
  auto testCase = ImageTestCase("gray-235-8bit-limited-range-grayscale.avif",
                                "image/avif", IntSize(100, 100));
  testCase.mColor = BGRAColor(0xEB, 0xEB, 0xEB, 0xFF);
  return testCase;
}

ImageTestCase Gray8bitFullRangeGrayscaleAVIFTestCase() {
  auto testCase = ImageTestCase("gray-235-8bit-full-range-grayscale.avif",
                                "image/avif", IntSize(100, 100));
  testCase.mColor = BGRAColor(0xEB, 0xEB, 0xEB, 0xFF);
  return testCase;
}

ImageTestCase Gray10bitLimitedRangeGrayscaleAVIFTestCase() {
  auto testCase = ImageTestCase("gray-235-10bit-limited-range-grayscale.avif",
                                "image/avif", IntSize(100, 100));
  // Small error is expected
  testCase.mColor = BGRAColor(0xEA, 0xEA, 0xEA, 0xFF);
  return testCase;
}

ImageTestCase Gray10bitFullRangeGrayscaleAVIFTestCase() {
  auto testCase = ImageTestCase("gray-235-10bit-full-range-grayscale.avif",
                                "image/avif", IntSize(100, 100));
  testCase.mColor = BGRAColor(0xEB, 0xEB, 0xEB, 0xFF);
  return testCase;
}

ImageTestCase Gray12bitLimitedRangeGrayscaleAVIFTestCase() {
  auto testCase = ImageTestCase("gray-235-12bit-limited-range-grayscale.avif",
                                "image/avif", IntSize(100, 100));
  // Small error is expected
  testCase.mColor = BGRAColor(0xEA, 0xEA, 0xEA, 0xFF);
  return testCase;
}

ImageTestCase Gray12bitFullRangeGrayscaleAVIFTestCase() {
  auto testCase = ImageTestCase("gray-235-12bit-full-range-grayscale.avif",
                                "image/avif", IntSize(100, 100));
  testCase.mColor = BGRAColor(0xEB, 0xEB, 0xEB, 0xFF);
  return testCase;
}

ImageTestCase StackCheckAVIFTestCase() {
  return ImageTestCase("stackcheck.avif""image/avif", IntSize(4096, 2924),
                       TEST_CASE_IGNORE_OUTPUT);
}

// Add TEST_CASE_IGNORE_OUTPUT since this isn't a solid green image and we just
// want to test that it decodes correctly.
ImageTestCase MultiLayerAVIFTestCase() {
  return ImageTestCase("multilayer.avif""image/avif", IntSize(1280, 720),
                       TEST_CASE_IGNORE_OUTPUT);
}

ImageTestCase LargeWebPTestCase() {
  return ImageTestCase("large.webp""image/webp", IntSize(1200, 660),
                       TEST_CASE_IGNORE_OUTPUT);
}

ImageTestCase LargeAVIFTestCase() {
  return ImageTestCase("large.avif""image/avif", IntSize(1200, 660),
                       TEST_CASE_IGNORE_OUTPUT);
}

ImageTestCase GreenWebPIccSrgbTestCase() {
  return ImageTestCase("green.icc_srgb.webp""image/webp", IntSize(100, 100));
}

ImageTestCase GreenFirstFrameAnimatedGIFTestCase() {
  return ImageTestCase("first-frame-green.gif""image/gif", IntSize(100, 100),
                       TEST_CASE_IS_ANIMATED, /* aFrameCount */ 2);
}

ImageTestCase GreenFirstFrameAnimatedPNGTestCase() {
  return ImageTestCase("first-frame-green.png""image/png", IntSize(100, 100),
                       TEST_CASE_IS_TRANSPARENT | TEST_CASE_IS_ANIMATED,
                       /* aFrameCount */ 2);
}

ImageTestCase GreenFirstFrameAnimatedWebPTestCase() {
  return ImageTestCase("first-frame-green.webp""image/webp",
                       IntSize(100, 100), TEST_CASE_IS_ANIMATED,
                       /* aFrameCount */ 2);
}

ImageTestCase GreenFirstFrameAnimatedAVIFTestCase() {
  return ImageTestCase("first-frame-green.avif""image/avif",
                       IntSize(100, 100), TEST_CASE_IS_ANIMATED,
                       /* aFrameCount */ 2);
}

ImageTestCase BlendAnimatedGIFTestCase() {
  return ImageTestCase("blend.gif""image/gif", IntSize(100, 100),
                       TEST_CASE_IS_ANIMATED, /* aFrameCount */ 2);
}

ImageTestCase BlendAnimatedPNGTestCase() {
  return ImageTestCase("blend.png""image/png", IntSize(100, 100),
                       TEST_CASE_IS_TRANSPARENT | TEST_CASE_IS_ANIMATED,
                       /* aFrameCount */ 2);
}

ImageTestCase BlendAnimatedWebPTestCase() {
  return ImageTestCase("blend.webp""image/webp", IntSize(100, 100),
                       TEST_CASE_IS_TRANSPARENT | TEST_CASE_IS_ANIMATED,
                       /* aFrameCount */ 2);
}

ImageTestCase BlendAnimatedAVIFTestCase() {
  return ImageTestCase("blend.avif""image/avif", IntSize(100, 100),
                       TEST_CASE_IS_TRANSPARENT | TEST_CASE_IS_ANIMATED,
                       /* aFrameCount */ 2);
}

ImageTestCase CorruptTestCase() {
  return ImageTestCase("corrupt.jpg""image/jpeg", IntSize(100, 100),
                       TEST_CASE_HAS_ERROR);
}

ImageTestCase CorruptBMPWithTruncatedHeader() {
  // This BMP has a header which is truncated right between the BIH and the
  // bitfields, which is a particularly error-prone place w.r.t. the BMP decoder
  // state machine.
  return ImageTestCase("invalid-truncated-metadata.bmp""image/bmp",
                       IntSize(100, 100), TEST_CASE_HAS_ERROR);
}

ImageTestCase CorruptICOWithBadBMPWidthTestCase() {
  // This ICO contains a BMP icon which has a width that doesn't match the size
  // listed in the corresponding ICO directory entry.
  return ImageTestCase("corrupt-with-bad-bmp-width.ico""image/x-icon",
                       IntSize(100, 100), TEST_CASE_HAS_ERROR);
}

ImageTestCase CorruptICOWithBadBMPHeightTestCase() {
  // This ICO contains a BMP icon which has a height that doesn't match the size
  // listed in the corresponding ICO directory entry.
  return ImageTestCase("corrupt-with-bad-bmp-height.ico""image/x-icon",
                       IntSize(100, 100), TEST_CASE_HAS_ERROR);
}

ImageTestCase CorruptICOWithBadBppTestCase() {
  // This test case is an ICO with a BPP (15) in the ICO header which differs
  // from that in the BMP header itself (1). It should ignore the ICO BPP when
  // the BMP BPP is available and thus correctly decode the image.
  return ImageTestCase("corrupt-with-bad-ico-bpp.ico""image/x-icon",
                       IntSize(100, 100), TEST_CASE_IS_TRANSPARENT);
}

ImageTestCase CorruptAVIFTestCase() {
  return ImageTestCase("bug-1655846.avif""image/avif", IntSize(100, 100),
                       TEST_CASE_HAS_ERROR);
}

ImageTestCase TransparentAVIFTestCase() {
  return ImageTestCase("transparent.avif""image/avif", IntSize(1200, 1200),
                       TEST_CASE_IS_TRANSPARENT);
}

ImageTestCase TransparentPNGTestCase() {
  return ImageTestCase("transparent.png""image/png", IntSize(32, 32),
                       TEST_CASE_IS_TRANSPARENT);
}

ImageTestCase TransparentGIFTestCase() {
  return ImageTestCase("transparent.gif""image/gif", IntSize(16, 16),
                       TEST_CASE_IS_TRANSPARENT);
}

ImageTestCase TransparentWebPTestCase() {
  ImageTestCase test("transparent.webp""image/webp", IntSize(100, 100),
                     TEST_CASE_IS_TRANSPARENT);
  test.mColor = BGRAColor::Transparent();
  return test;
}

ImageTestCase TransparentNoAlphaHeaderWebPTestCase() {
  ImageTestCase test("transparent-no-alpha-header.webp""image/webp",
                     IntSize(100, 100), TEST_CASE_IS_FUZZY);
  test.mColor = BGRAColor(0x00, 0x00, 0x00, 0xFF);  // black
  return test;
}

ImageTestCase FirstFramePaddingGIFTestCase() {
  return ImageTestCase("transparent.gif""image/gif", IntSize(16, 16),
                       TEST_CASE_IS_TRANSPARENT);
}

ImageTestCase TransparentIfWithinICOBMPTestCase(TestCaseFlags aFlags) {
  // This is a BMP that is only transparent when decoded as if it is within an
  // ICO file. (Note: aFlags needs to be set to TEST_CASE_DEFAULT_FLAGS or
  // TEST_CASE_IS_TRANSPARENT accordingly.)
  return ImageTestCase("transparent-if-within-ico.bmp""image/bmp",
                       IntSize(32, 32), aFlags);
}

ImageTestCase RLE4BMPTestCase() {
  return ImageTestCase("rle4.bmp""image/bmp", IntSize(320, 240),
                       TEST_CASE_IS_TRANSPARENT);
}

ImageTestCase RLE8BMPTestCase() {
  return ImageTestCase("rle8.bmp""image/bmp", IntSize(32, 32),
                       TEST_CASE_IS_TRANSPARENT);
}

ImageTestCase NoFrameDelayGIFTestCase() {
  // This is an invalid (or at least, questionably valid) GIF that's animated
  // even though it specifies a frame delay of zero. It's animated, but it's not
  // marked TEST_CASE_IS_ANIMATED because the metadata decoder can't detect that
  // it's animated.
  return ImageTestCase("no-frame-delay.gif""image/gif", IntSize(100, 100));
}

ImageTestCase ExtraImageSubBlocksAnimatedGIFTestCase() {
  // This is a corrupt GIF that has extra image sub blocks between the first and
  // second frame.
  return ImageTestCase("animated-with-extra-image-sub-blocks.gif""image/gif",
                       IntSize(100, 100));
}

ImageTestCase DownscaledPNGTestCase() {
  // This testcase (and all the other "downscaled") testcases) consists of 25
  // lines of green, followed by 25 lines of red, followed by 25 lines of green,
  // followed by 25 more lines of red. It's intended that tests downscale it
  // from 100x100 to 20x20, so we specify a 20x20 output size.
  return ImageTestCase("downscaled.png""image/png", IntSize(100, 100),
                       IntSize(20, 20));
}

ImageTestCase DownscaledGIFTestCase() {
  return ImageTestCase("downscaled.gif""image/gif", IntSize(100, 100),
                       IntSize(20, 20));
}

ImageTestCase DownscaledJPGTestCase() {
  return ImageTestCase("downscaled.jpg""image/jpeg", IntSize(100, 100),
                       IntSize(20, 20));
}

ImageTestCase DownscaledBMPTestCase() {
  return ImageTestCase("downscaled.bmp""image/bmp", IntSize(100, 100),
                       IntSize(20, 20));
}

ImageTestCase DownscaledICOTestCase() {
  return ImageTestCase("downscaled.ico""image/x-icon", IntSize(100, 100),
                       IntSize(20, 20), TEST_CASE_IS_TRANSPARENT);
}

ImageTestCase DownscaledIconTestCase() {
  return ImageTestCase("downscaled.icon""image/icon", IntSize(100, 100),
                       IntSize(20, 20), TEST_CASE_IS_TRANSPARENT);
}

ImageTestCase DownscaledWebPTestCase() {
  return ImageTestCase("downscaled.webp""image/webp", IntSize(100, 100),
                       IntSize(20, 20));
}

ImageTestCase DownscaledAVIFTestCase() {
  return ImageTestCase("downscaled.avif""image/avif", IntSize(100, 100),
                       IntSize(20, 20));
}

ImageTestCase DownscaledTransparentICOWithANDMaskTestCase() {
  // This test case is an ICO with AND mask transparency. We want to ensure that
  // we can downscale it without crashing or triggering ASAN failures, but its
  // content isn't simple to verify, so for now we don't check the output.
  return ImageTestCase("transparent-ico-with-and-mask.ico""image/x-icon",
                       IntSize(32, 32), IntSize(20, 20),
                       TEST_CASE_IS_TRANSPARENT | TEST_CASE_IGNORE_OUTPUT);
}

ImageTestCase TruncatedSmallGIFTestCase() {
  return ImageTestCase("green-1x1-truncated.gif""image/gif", IntSize(1, 1),
                       TEST_CASE_IS_TRANSPARENT);
}

ImageTestCase LargeICOWithBMPTestCase() {
  return ImageTestCase("green-large-bmp.ico""image/x-icon", IntSize(256, 256),
                       TEST_CASE_IS_TRANSPARENT);
}

ImageTestCase LargeICOWithPNGTestCase() {
  return ImageTestCase("green-large-png.ico""image/x-icon", IntSize(512, 512),
                       TEST_CASE_IS_TRANSPARENT);
}

ImageTestCase GreenMultipleSizesICOTestCase() {
  return ImageTestCase("green-multiple-sizes.ico""image/x-icon",
                       IntSize(256, 256));
}

ImageTestCase PerfGrayJPGTestCase() {
  return ImageTestCase("perf_gray.jpg""image/jpeg", IntSize(1000, 1000));
}

ImageTestCase PerfCmykJPGTestCase() {
  return ImageTestCase("perf_cmyk.jpg""image/jpeg", IntSize(1000, 1000));
}

ImageTestCase PerfYCbCrJPGTestCase() {
  return ImageTestCase("perf_ycbcr.jpg""image/jpeg", IntSize(1000, 1000));
}

ImageTestCase PerfRgbPNGTestCase() {
  return ImageTestCase("perf_srgb.png""image/png", IntSize(1000, 1000));
}

ImageTestCase PerfRgbAlphaPNGTestCase() {
  return ImageTestCase("perf_srgb_alpha.png""image/png", IntSize(1000, 1000),
                       TEST_CASE_IS_TRANSPARENT);
}

ImageTestCase PerfGrayPNGTestCase() {
  return ImageTestCase("perf_gray.png""image/png", IntSize(1000, 1000));
}

ImageTestCase PerfGrayAlphaPNGTestCase() {
  return ImageTestCase("perf_gray_alpha.png""image/png", IntSize(1000, 1000),
                       TEST_CASE_IS_TRANSPARENT);
}

ImageTestCase PerfRgbLosslessWebPTestCase() {
  return ImageTestCase("perf_srgb_lossless.webp""image/webp",
                       IntSize(1000, 1000));
}

ImageTestCase PerfRgbAlphaLosslessWebPTestCase() {
  return ImageTestCase("perf_srgb_alpha_lossless.webp""image/webp",
                       IntSize(1000, 1000), TEST_CASE_IS_TRANSPARENT);
}

ImageTestCase PerfRgbLossyWebPTestCase() {
  return ImageTestCase("perf_srgb_lossy.webp""image/webp",
                       IntSize(1000, 1000));
}

ImageTestCase PerfRgbAlphaLossyWebPTestCase() {
  return ImageTestCase("perf_srgb_alpha_lossy.webp""image/webp",
                       IntSize(1000, 1000), TEST_CASE_IS_TRANSPARENT);
}

ImageTestCase PerfRgbGIFTestCase() {
  return ImageTestCase("perf_srgb.gif""image/gif", IntSize(1000, 1000));
}

#ifdef MOZ_JXL
ImageTestCase GreenJXLTestCase() {
  return ImageTestCase("green.jxl""image/jxl", IntSize(100, 100));
}

ImageTestCase DownscaledJXLTestCase() {
  return ImageTestCase("downscaled.jxl""image/jxl", IntSize(100, 100),
                       IntSize(20, 20));
}

ImageTestCase LargeJXLTestCase() {
  return ImageTestCase("large.jxl""image/jxl", IntSize(1200, 660),
                       TEST_CASE_IGNORE_OUTPUT);
}

ImageTestCase TransparentJXLTestCase() {
  return ImageTestCase("transparent.jxl""image/jxl", IntSize(1200, 1200),
                       TEST_CASE_IS_TRANSPARENT);
}
#endif

ImageTestCase ExifResolutionTestCase() {
  return ImageTestCase("exif_resolution.jpg""image/jpeg", IntSize(100, 50));
}

RefPtr<Image> TestCaseToDecodedImage(const ImageTestCase& aTestCase) {
  RefPtr<Image> image = ImageFactory::CreateAnonymousImage(
      nsDependentCString(aTestCase.mMimeType));
  MOZ_RELEASE_ASSERT(!image->HasError());

  nsCOMPtr<nsIInputStream> inputStream = LoadFile(aTestCase.mPath);
  MOZ_RELEASE_ASSERT(inputStream);

  // Figure out how much data we have.
  uint64_t length;
  nsresult rv = inputStream->Available(&length);
  MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));

  // Write the data into the image.
  rv = image->OnImageDataAvailable(nullptr, inputStream, 0,
                                   static_cast<uint32_t>(length));
  MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));

  // Let the image know we've sent all the data.
  rv = image->OnImageDataComplete(nullptr, NS_OK, true);
  MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));

  RefPtr<ProgressTracker> tracker = image->GetProgressTracker();
  tracker->SyncNotifyProgress(FLAG_LOAD_COMPLETE);

  // Use GetFrame() to force a sync decode of the image.
  RefPtr<SourceSurface> surface = image->GetFrame(
      imgIContainer::FRAME_CURRENT, imgIContainer::FLAG_SYNC_DECODE);
  Unused << surface;
  return image;
}

}  // namespace image
}  // namespace mozilla

Messung V0.5
C=89 H=97 G=93

¤ Dauer der Verarbeitung: 0.47 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

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.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge