NS_IMETHODIMP imgTools::DecodeImageData(nsIInputStream* aInStr, const nsACString& aMimeType, imgIContainer **aContainer) { nsresult rv; RasterImage* image; // convenience alias for *aContainer NS_ENSURE_ARG_POINTER(aInStr); // If the caller didn't provide an imgIContainer, create one. if (*aContainer) { NS_ABORT_IF_FALSE((*aContainer)->GetType() == imgIContainer::TYPE_RASTER, "wrong type of imgIContainer for decoding into"); image = static_cast<RasterImage*>(*aContainer); } else { *aContainer = image = new RasterImage(); NS_ADDREF(image); } // Initialize the Image. If we're using the one from the caller, we // require that it not be initialized. nsCString mimeType(aMimeType); rv = image->Init(nullptr, mimeType.get(), "<unknown>", Image::INIT_FLAG_NONE); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIInputStream> inStream = aInStr; if (!NS_InputStreamIsBuffered(aInStr)) { nsCOMPtr<nsIInputStream> bufStream; rv = NS_NewBufferedInputStream(getter_AddRefs(bufStream), aInStr, 1024); if (NS_SUCCEEDED(rv)) inStream = bufStream; } // Figure out how much data we've been passed uint64_t length; rv = inStream->Available(&length); NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_TRUE(length <= UINT32_MAX, NS_ERROR_FILE_TOO_BIG); // Send the source data to the Image. WriteToRasterImage always // consumes everything it gets if it doesn't run out of memory. uint32_t bytesRead; rv = inStream->ReadSegments(RasterImage::WriteToRasterImage, static_cast<void*>(image), (uint32_t)length, &bytesRead); NS_ENSURE_SUCCESS(rv, rv); NS_ABORT_IF_FALSE(bytesRead == length || image->HasError(), "WriteToRasterImage should consume everything or the image must be in error!"); // Let the Image know we've sent all the data rv = image->SourceDataComplete(); NS_ENSURE_SUCCESS(rv, rv); // All done return NS_OK; }