ImageData* ImageData::create(unsigned width, unsigned height, ExceptionState& exceptionState) { if (!width || !height) { exceptionState.throwDOMException( IndexSizeError, String::format("The source %s is zero or not a number.", width ? "height" : "width")); return nullptr; } CheckedNumeric<unsigned> dataSize = 4; dataSize *= width; dataSize *= height; if (!dataSize.IsValid() || static_cast<int>(width) < 0 || static_cast<int>(height) < 0) { exceptionState.throwDOMException( IndexSizeError, "The requested image size exceeds the supported range."); return nullptr; } DOMUint8ClampedArray* byteArray = DOMUint8ClampedArray::createOrNull(dataSize.ValueOrDie()); if (!byteArray) { exceptionState.throwDOMException(V8Error, "Out of memory at ImageData creation"); return nullptr; } return new ImageData(IntSize(width, height), byteArray); }
ImageData* ImageData::create(const IntSize& size) { CheckedNumeric<int> dataSize = 4; dataSize *= size.width(); dataSize *= size.height(); if (!dataSize.IsValid() || dataSize.ValueOrDie() < 0) return nullptr; DOMUint8ClampedArray* byteArray = DOMUint8ClampedArray::createOrNull(dataSize.ValueOrDie()); if (!byteArray) return nullptr; return new ImageData(size, byteArray); }
ImageData* ImageData::create(const IntSize& size, DOMUint8ClampedArray* byteArray) { CheckedNumeric<int> dataSize = 4; dataSize *= size.width(); dataSize *= size.height(); if (!dataSize.IsValid()) return nullptr; if (dataSize.ValueOrDie() < 0 || static_cast<unsigned>(dataSize.ValueOrDie()) > byteArray->length()) return nullptr; return new ImageData(size, byteArray); }
bool ImageBuffer::getImageData(Multiply multiplied, const IntRect& rect, WTF::ArrayBufferContents& contents) const { CheckedNumeric<int> dataSize = 4; dataSize *= rect.width(); dataSize *= rect.height(); if (!dataSize.IsValid()) return false; if (!isSurfaceValid()) { size_t allocSizeInBytes = rect.width() * rect.height() * 4; void* data; WTF::ArrayBufferContents::allocateMemoryOrNull(allocSizeInBytes, WTF::ArrayBufferContents::ZeroInitialize, data); if (!data) return false; WTF::ArrayBufferContents result(data, allocSizeInBytes, WTF::ArrayBufferContents::NotShared); result.transfer(contents); return true; } DCHECK(canvas()); RefPtr<SkImage> snapshot = m_surface->newImageSnapshot(PreferNoAcceleration, SnapshotReasonGetImageData); if (!snapshot) return false; const bool mayHaveStrayArea = m_surface->isAccelerated() // GPU readback may fail silently || rect.x() < 0 || rect.y() < 0 || rect.maxX() > m_surface->size().width() || rect.maxY() > m_surface->size().height(); size_t allocSizeInBytes = rect.width() * rect.height() * 4; void* data; WTF::ArrayBufferContents::InitializationPolicy initializationPolicy = mayHaveStrayArea ? WTF::ArrayBufferContents::ZeroInitialize : WTF::ArrayBufferContents::DontInitialize; WTF::ArrayBufferContents::allocateMemoryOrNull(allocSizeInBytes, initializationPolicy, data); if (!data) return false; WTF::ArrayBufferContents result(data, allocSizeInBytes, WTF::ArrayBufferContents::NotShared); SkAlphaType alphaType = (multiplied == Premultiplied) ? kPremul_SkAlphaType : kUnpremul_SkAlphaType; SkImageInfo info = SkImageInfo::Make(rect.width(), rect.height(), kRGBA_8888_SkColorType, alphaType); snapshot->readPixels(info, result.data(), 4 * rect.width(), rect.x(), rect.y()); result.transfer(contents); return true; }
bool DrawingBuffer::paintRenderingResultsToImageData(int& width, int& height, SourceDrawingBuffer sourceBuffer, WTF::ArrayBufferContents& contents) { ASSERT(!m_premultipliedAlpha); width = size().width(); height = size().height(); CheckedNumeric<int> dataSize = 4; dataSize *= width; dataSize *= height; if (!dataSize.IsValid()) return false; WTF::ArrayBufferContents pixels(width * height, 4, WTF::ArrayBufferContents::NotShared, WTF::ArrayBufferContents::DontInitialize); GLuint fbo = 0; if (sourceBuffer == FrontBuffer && m_frontColorBuffer.texInfo.textureId) { m_gl->GenFramebuffers(1, &fbo); m_gl->BindFramebuffer(GL_FRAMEBUFFER, fbo); m_gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_frontColorBuffer.texInfo.parameters.target, m_frontColorBuffer.texInfo.textureId, 0); } else { m_gl->BindFramebuffer(GL_FRAMEBUFFER, framebuffer()); } readBackFramebuffer(static_cast<unsigned char*>(pixels.data()), width, height, ReadbackRGBA, WebGLImageConversion::AlphaDoNothing); flipVertically(static_cast<uint8_t*>(pixels.data()), width, height); if (fbo) { m_gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_frontColorBuffer.texInfo.parameters.target, 0, 0); m_gl->DeleteFramebuffers(1, &fbo); } restoreFramebufferBindings(); pixels.transfer(contents); return true; }