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