static void CheckDecoderSingleChunk(const ImageTestCase& aTestCase) { nsCOMPtr<nsIInputStream> inputStream = LoadFile(aTestCase.mPath); ASSERT_TRUE(inputStream != nullptr); // Figure out how much data we have. uint64_t length; nsresult rv = inputStream->Available(&length); ASSERT_TRUE(NS_SUCCEEDED(rv)); // Write the data into a SourceBuffer. RefPtr<SourceBuffer> sourceBuffer = new SourceBuffer(); sourceBuffer->ExpectLength(length); rv = sourceBuffer->AppendFromInputStream(inputStream, length); ASSERT_TRUE(NS_SUCCEEDED(rv)); sourceBuffer->Complete(NS_OK); // Create a decoder. DecoderType decoderType = DecoderFactory::GetDecoderType(aTestCase.mMimeType); RefPtr<Decoder> decoder = DecoderFactory::CreateAnonymousDecoder(decoderType, sourceBuffer, DefaultSurfaceFlags()); ASSERT_TRUE(decoder != nullptr); // Run the full decoder synchronously. decoder->Decode(); CheckDecoderResults(aTestCase, decoder); }
/* static */ already_AddRefed<gfx::SourceSurface> ImageOps::DecodeToSurface(nsIInputStream* aInputStream, const nsACString& aMimeType, uint32_t aFlags) { MOZ_ASSERT(aInputStream); nsresult rv; // Prepare the input stream. nsCOMPtr<nsIInputStream> inputStream = aInputStream; if (!NS_InputStreamIsBuffered(aInputStream)) { nsCOMPtr<nsIInputStream> bufStream; rv = NS_NewBufferedInputStream(getter_AddRefs(bufStream), aInputStream, 1024); if (NS_SUCCEEDED(rv)) { inputStream = bufStream; } } // Figure out how much data we've been passed. uint64_t length; rv = inputStream->Available(&length); if (NS_FAILED(rv) || length > UINT32_MAX) { return nullptr; } // Write the data into a SourceBuffer. RefPtr<SourceBuffer> sourceBuffer = new SourceBuffer(); sourceBuffer->ExpectLength(length); rv = sourceBuffer->AppendFromInputStream(inputStream, length); if (NS_FAILED(rv)) { return nullptr; } sourceBuffer->Complete(NS_OK); // Create a decoder. DecoderType decoderType = DecoderFactory::GetDecoderType(PromiseFlatCString(aMimeType).get()); RefPtr<Decoder> decoder = DecoderFactory::CreateAnonymousDecoder(decoderType, sourceBuffer, ToSurfaceFlags(aFlags)); if (!decoder) { return nullptr; } // Run the decoder synchronously. decoder->Decode(); if (!decoder->GetDecodeDone() || decoder->HasError()) { return nullptr; } // Pull out the surface. RawAccessFrameRef frame = decoder->GetCurrentFrameRef(); if (!frame) { return nullptr; } RefPtr<SourceSurface> surface = frame->GetSurface(); if (!surface) { return nullptr; } return surface.forget(); }
static void CheckMetadata(const ImageTestCase& aTestCase, BMPAlpha aBMPAlpha = BMPAlpha::DISABLED) { nsCOMPtr<nsIInputStream> inputStream = LoadFile(aTestCase.mPath); ASSERT_TRUE(inputStream != nullptr); // Figure out how much data we have. uint64_t length; nsresult rv = inputStream->Available(&length); ASSERT_TRUE(NS_SUCCEEDED(rv)); // Write the data into a SourceBuffer. RefPtr<SourceBuffer> sourceBuffer = new SourceBuffer(); sourceBuffer->ExpectLength(length); rv = sourceBuffer->AppendFromInputStream(inputStream, length); ASSERT_TRUE(NS_SUCCEEDED(rv)); sourceBuffer->Complete(NS_OK); // Create a metadata decoder. DecoderType decoderType = DecoderFactory::GetDecoderType(aTestCase.mMimeType); RefPtr<Decoder> decoder = DecoderFactory::CreateAnonymousMetadataDecoder(decoderType, sourceBuffer); ASSERT_TRUE(decoder != nullptr); if (aBMPAlpha == BMPAlpha::ENABLED) { static_cast<nsBMPDecoder*>(decoder.get())->SetUseAlphaData(true); } // Run the metadata decoder synchronously. decoder->Decode(); // Ensure that the metadata decoder didn't make progress it shouldn't have // (which would indicate that it decoded past the header of the image). Progress metadataProgress = decoder->TakeProgress(); EXPECT_TRUE(0 == (metadataProgress & ~(FLAG_SIZE_AVAILABLE | FLAG_HAS_TRANSPARENCY | FLAG_IS_ANIMATED))); // If the test case is corrupt, assert what we can and return early. if (aTestCase.mFlags & TEST_CASE_HAS_ERROR) { EXPECT_TRUE(decoder->GetDecodeDone()); EXPECT_TRUE(decoder->HasError()); return; } EXPECT_TRUE(decoder->GetDecodeDone() && !decoder->HasError()); // Check that we got the expected metadata. EXPECT_TRUE(metadataProgress & FLAG_SIZE_AVAILABLE); IntSize metadataSize = decoder->GetSize(); EXPECT_EQ(aTestCase.mSize.width, metadataSize.width); EXPECT_EQ(aTestCase.mSize.height, metadataSize.height); bool expectTransparency = aBMPAlpha == BMPAlpha::ENABLED ? true : bool(aTestCase.mFlags & TEST_CASE_IS_TRANSPARENT); EXPECT_EQ(expectTransparency, bool(metadataProgress & FLAG_HAS_TRANSPARENCY)); EXPECT_EQ(bool(aTestCase.mFlags & TEST_CASE_IS_ANIMATED), bool(metadataProgress & FLAG_IS_ANIMATED)); // Create a full decoder, so we can compare the result. decoder = DecoderFactory::CreateAnonymousDecoder(decoderType, sourceBuffer, DefaultSurfaceFlags()); ASSERT_TRUE(decoder != nullptr); if (aBMPAlpha == BMPAlpha::ENABLED) { static_cast<nsBMPDecoder*>(decoder.get())->SetUseAlphaData(true); } // Run the full decoder synchronously. decoder->Decode(); EXPECT_TRUE(decoder->GetDecodeDone() && !decoder->HasError()); Progress fullProgress = decoder->TakeProgress(); // If the metadata decoder set a progress bit, the full decoder should also // have set the same bit. EXPECT_EQ(fullProgress, metadataProgress | fullProgress); // The full decoder and the metadata decoder should agree on the image's size. IntSize fullSize = decoder->GetSize(); EXPECT_EQ(metadataSize.width, fullSize.width); EXPECT_EQ(metadataSize.height, fullSize.height); // We should not discover transparency during the full decode that we didn't // discover during the metadata decode, unless the image is animated. EXPECT_TRUE(!(fullProgress & FLAG_HAS_TRANSPARENCY) || (metadataProgress & FLAG_HAS_TRANSPARENCY) || (fullProgress & FLAG_IS_ANIMATED)); }