ImageDecoderDirect2D.cpp [plain text]
#include "config.h"
#include "ImageDecoderDirect2D.h"
#if USE(DIRECT2D)
#include "GraphicsContext.h"
#include "ImageOrientation.h"
#include "IntPoint.h"
#include "IntSize.h"
#include "Logging.h"
#include "NotImplemented.h"
#include "SharedBuffer.h"
#include <WinCodec.h>
#include <d2d1.h>
#include <wtf/NeverDestroyed.h>
#include <wtf/Optional.h>
namespace WebCore {
ImageDecoderDirect2D::ImageDecoderDirect2D()
{
}
IWICImagingFactory2* ImageDecoderDirect2D::systemImagingFactory()
{
static IWICImagingFactory2* wicImagingFactory = nullptr;
if (!wicImagingFactory) {
HRESULT hr = CoCreateInstance(CLSID_WICImagingFactory, nullptr, CLSCTX_INPROC_SERVER, IID_IWICImagingFactory2, (LPVOID*)&wicImagingFactory);
RELEASE_ASSERT(SUCCEEDED(hr));
}
return wicImagingFactory;
}
size_t ImageDecoderDirect2D::bytesDecodedToDetermineProperties() const
{
return 13088;
}
String ImageDecoderDirect2D::filenameExtension() const
{
notImplemented();
return String();
}
bool ImageDecoderDirect2D::isSizeAvailable() const
{
return m_nativeDecoder ? true : false;
}
EncodedDataStatus ImageDecoderDirect2D::encodedDataStatus() const
{
if (!m_nativeDecoder)
return EncodedDataStatus::Error;
return EncodedDataStatus::Complete;
}
IntSize ImageDecoderDirect2D::size() const
{
if (!m_nativeDecoder)
return IntSize();
COMPtr<IWICBitmapFrameDecode> frame;
HRESULT hr = m_nativeDecoder->GetFrame(0, &frame);
if (!SUCCEEDED(hr))
return IntSize();
UINT width, height;
hr = frame->GetSize(&width, &height);
if (!SUCCEEDED(hr))
return IntSize();
return IntSize(width, height);
}
size_t ImageDecoderDirect2D::frameCount() const
{
if (!m_nativeDecoder)
return 0;
UINT count;
HRESULT hr = m_nativeDecoder->GetFrameCount(&count);
if (!SUCCEEDED(hr))
return 0;
return count;
}
RepetitionCount ImageDecoderDirect2D::repetitionCount() const
{
if (!m_nativeDecoder)
return RepetitionCountNone;
return RepetitionCountNone;
}
Optional<IntPoint> ImageDecoderDirect2D::hotSpot() const
{
return WTF::nullopt;
}
IntSize ImageDecoderDirect2D::frameSizeAtIndex(size_t index, SubsamplingLevel subsamplingLevel) const
{
if (!m_nativeDecoder)
return IntSize();
COMPtr<IWICBitmapFrameDecode> frame;
HRESULT hr = m_nativeDecoder->GetFrame(index, &frame);
if (!SUCCEEDED(hr))
return IntSize();
UINT width, height;
hr = frame->GetSize(&width, &height);
if (!SUCCEEDED(hr))
return IntSize();
return IntSize(width, height);
}
bool ImageDecoderDirect2D::frameIsCompleteAtIndex(size_t index) const
{
if (!m_nativeDecoder)
return false;
COMPtr<IWICBitmapFrameDecode> frame;
HRESULT hr = m_nativeDecoder->GetFrame(index, &frame);
return SUCCEEDED(hr);
}
ImageDecoder::FrameMetadata ImageDecoderDirect2D::frameMetadataAtIndex(size_t) const final;
{
if (!m_nativeDecoder)
return { };
COMPtr<IWICBitmapFrameDecode> frame;
HRESULT hr = m_nativeDecoder->GetFrame(index, &frame);
if (!SUCCEEDED(hr))
return { };
COMPtr<IWICMetadataQueryReader> metadata;
hr = frame->GetMetadataQueryReader(&metadata);
if (!SUCCEEDED(hr))
return { };
PROPVARIANT value;
PropVariantInit(&value);
hr = metadata->GetMetadataByName(L"System.Photo.Orientation", &value);
if (SUCCEEDED(hr))
return { ImageOrientation(static_cast<ImageOrientation::Orientation>(value.uiVal)), WTF::nullopt };
return { };
}
Seconds ImageDecoderDirect2D::frameDurationAtIndex(size_t index) const
{
if (!m_nativeDecoder)
return Seconds(0);
COMPtr<IWICBitmapFrameDecode> frame;
HRESULT hr = m_nativeDecoder->GetFrame(index, &frame);
if (!SUCCEEDED(hr))
return Seconds(0);
notImplemented();
return Seconds(0);
}
bool ImageDecoderDirect2D::frameAllowSubsamplingAtIndex(size_t index) const
{
return true;
}
bool ImageDecoderDirect2D::frameHasAlphaAtIndex(size_t index) const
{
if (!m_nativeDecoder)
return false;
COMPtr<IWICBitmapFrameDecode> frame;
HRESULT hr = m_nativeDecoder->GetFrame(index, &frame);
if (!SUCCEEDED(hr))
return false;
COMPtr<IWICMetadataQueryReader> metadata;
hr = frame->GetMetadataQueryReader(&metadata);
if (!SUCCEEDED(hr))
return false;
GUID containerFormat;
hr = metadata->GetContainerFormat(&containerFormat);
if (!SUCCEEDED(hr))
return false;
if (::IsEqualGUID(GUID_ContainerFormatJpeg, containerFormat))
return false;
return true;
}
unsigned ImageDecoderDirect2D::frameBytesAtIndex(size_t index, SubsamplingLevel subsamplingLevel) const
{
if (!m_nativeDecoder)
return 0;
auto frameSize = frameSizeAtIndex(index, subsamplingLevel);
return (frameSize.area() * 4).unsafeGet();
}
void ImageDecoderDirect2D::setTargetContext(ID2D1RenderTarget* renderTarget)
{
m_renderTarget = renderTarget;
}
PlatformImagePtr ImageDecoderDirect2D::createFrameImageAtIndex(size_t index, SubsamplingLevel subsamplingLevel, const DecodingOptions&)
{
if (!m_nativeDecoder)
return nullptr;
if (!m_renderTarget)
return nullptr;
COMPtr<IWICBitmapFrameDecode> frame;
HRESULT hr = m_nativeDecoder->GetFrame(0, &frame);
if (!SUCCEEDED(hr))
return nullptr;
COMPtr<IWICFormatConverter> converter;
hr = systemImagingFactory()->CreateFormatConverter(&converter);
if (!SUCCEEDED(hr))
return nullptr;
hr = converter->Initialize(frame.get(), GUID_WICPixelFormat32bppPRGBA, WICBitmapDitherTypeNone, nullptr, 0.f, WICBitmapPaletteTypeCustom);
if (!SUCCEEDED(hr))
return nullptr;
COMPtr<IWICBitmap> wicBitmap;
hr = systemImagingFactory()->CreateBitmapFromSource(converter.get(), WICBitmapCacheOnDemand, &wicBitmap);
if (!SUCCEEDED(hr))
return nullptr;
COMPtr<ID2D1Bitmap> bitmap;
hr = m_renderTarget->CreateBitmapFromWicBitmap(wicBitmap.get(), &bitmap);
if (!SUCCEEDED(hr))
return nullptr;
return bitmap;
}
void ImageDecoderDirect2D::setData(SharedBuffer& data, bool allDataReceived)
{
if (!allDataReceived)
return;
COMPtr<IWICStream> stream;
HRESULT hr = systemImagingFactory()->CreateStream(&stream);
if (!SUCCEEDED(hr))
return;
char* dataPtr = const_cast<char*>(data.data());
hr = stream->InitializeFromMemory(reinterpret_cast<BYTE*>(dataPtr), data.size());
if (!SUCCEEDED(hr))
return;
m_nativeDecoder = nullptr;
hr = systemImagingFactory()->CreateDecoderFromStream(stream.get(), nullptr, WICDecodeMetadataCacheOnDemand, &m_nativeDecoder);
if (!SUCCEEDED(hr)) {
m_nativeDecoder = nullptr;
return;
}
}
}
#endif