PassRefPtr<ByteArray> ImageBuffer::getUnmultipliedImageData(const IntRect& rect) const { GraphicsContext* gc = this->context(); if (!gc) { return 0; } const SkBitmap& src = imageBufferCanvas(this)->getDevice()->accessBitmap(false); SkAutoLockPixels alp(src); if (!src.getPixels()) { return 0; } RefPtr<ByteArray> result = ByteArray::create(rect.width() * rect.height() * 4); unsigned char* data = result->data(); if (rect.x() < 0 || rect.y() < 0 || rect.maxX() > m_size.width() || rect.maxY() > m_size.height()) memset(data, 0, result->length()); int originx = rect.x(); int destx = 0; if (originx < 0) { destx = -originx; originx = 0; } int endx = rect.x() + rect.width(); if (endx > m_size.width()) endx = m_size.width(); int numColumns = endx - originx; int originy = rect.y(); int desty = 0; if (originy < 0) { desty = -originy; originy = 0; } int endy = rect.y() + rect.height(); if (endy > m_size.height()) endy = m_size.height(); int numRows = endy - originy; unsigned srcPixelsPerRow = src.rowBytesAsPixels(); unsigned destBytesPerRow = 4 * rect.width(); /// M: change process to read pixel @{ /* fix w3c pixel manipulation relative test case */ SkBitmap destBitmap; destBitmap.setConfig(SkBitmap::kARGB_8888_Config, rect.width(), rect.height(), destBytesPerRow); destBitmap.setPixels(data); SkCanvas* canvas = imageBufferCanvas(this); canvas->readPixels(&destBitmap, rect.x(), rect.y(), SkCanvas::kRGBA_Unpremul_Config8888); return result.release(); /// @} }
void ImageBuffer::putUnmultipliedImageData(ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint) { GraphicsContext* gc = this->context(); if (!gc) { return; } const SkBitmap& dst = imageBufferCanvas(this)->getDevice()->accessBitmap(true); SkAutoLockPixels alp(dst); if (!dst.getPixels()) { return; } ASSERT(sourceRect.width() > 0); ASSERT(sourceRect.height() > 0); int originx = sourceRect.x(); int destx = destPoint.x() + sourceRect.x(); ASSERT(destx >= 0); ASSERT(destx < m_size.width()); ASSERT(originx >= 0); ASSERT(originx <= sourceRect.maxX()); int endx = destPoint.x() + sourceRect.maxX(); ASSERT(endx <= m_size.width()); int numColumns = endx - destx; int originy = sourceRect.y(); int desty = destPoint.y() + sourceRect.y(); ASSERT(desty >= 0); ASSERT(desty < m_size.height()); ASSERT(originy >= 0); ASSERT(originy <= sourceRect.maxY()); int endy = destPoint.y() + sourceRect.maxY(); ASSERT(endy <= m_size.height()); int numRows = endy - desty; unsigned srcBytesPerRow = 4 * sourceSize.width(); unsigned dstPixelsPerRow = dst.rowBytesAsPixels(); unsigned char* srcRows = source->data() + originy * srcBytesPerRow + originx * 4; SkPMColor* dstRows = dst.getAddr32(destx, desty); for (int y = 0; y < numRows; ++y) { for (int x = 0; x < numColumns; x++) { int basex = x * 4; dstRows[x] = SkPackARGB32(srcRows[basex + 3], srcRows[basex + 0], srcRows[basex + 1], srcRows[basex + 2]); } dstRows += dstPixelsPerRow; srcRows += srcBytesPerRow; } }
/// M: added for HTML5-benchmark performance @{ PassRefPtr<Image> ImageBuffer::getContextImageRef() const { SkCanvas* canvas = imageBufferCanvas(this); if (!canvas) return 0; SkDevice* device = canvas->getDevice(); const SkBitmap& orig = device->accessBitmap(false); SkBitmapRef* ref = new SkBitmapRef(orig); RefPtr<Image> image = BitmapImage::create(ref, 0); ref->unref(); return image; }
void ImageBuffer::putUnmultipliedImageData(ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint) { GraphicsContext* gc = this->context(); if (!gc) { return; } ASSERT(sourceRect.width() > 0); ASSERT(sourceRect.height() > 0); int originx = sourceRect.x(); int destx = destPoint.x() + sourceRect.x(); ASSERT(destx >= 0); ASSERT(destx < m_size.width()); ASSERT(originx >= 0); ASSERT(originx <= sourceRect.maxX()); int endx = destPoint.x() + sourceRect.maxX(); ASSERT(endx <= m_size.width()); int numColumns = endx - destx; int originy = sourceRect.y(); int desty = destPoint.y() + sourceRect.y(); ASSERT(desty >= 0); ASSERT(desty < m_size.height()); ASSERT(originy >= 0); ASSERT(originy <= sourceRect.maxY()); int endy = destPoint.y() + sourceRect.maxY(); ASSERT(endy <= m_size.height()); int numRows = endy - desty; unsigned srcBytesPerRow = 4 * sourceSize.width(); SkBitmap srcBitmap; /// M: change process to write pixel @{ /* fix w3c pixel manipulation relative test case */ srcBitmap.setConfig(SkBitmap::kARGB_8888_Config, numColumns, numRows, srcBytesPerRow); srcBitmap.setPixels(source->data() + originy * srcBytesPerRow + originx * 4); SkCanvas* canvas = imageBufferCanvas(this); canvas->writePixels(srcBitmap, destx, desty, SkCanvas::kRGBA_Unpremul_Config8888); /// @} }
bool CanvasTexture::uploadImageBuffer(ImageBuffer* imageBuffer) { m_hasValidTexture = false; SurfaceTextureClient* anw = nativeWindow(); if (!anw || ! imageBuffer) // CAPPFIX_WEB_NULL_CHECK_CANVASTEXTURE return false; // Size mismatch, early abort (will fall back to software) if (imageBuffer->size() != m_size) return false; SkCanvas* canvas = imageBufferCanvas(imageBuffer); if (!canvas) return false; const SkBitmap& bitmap = canvas->getDevice()->accessBitmap(false); if (!GLUtils::updateSharedSurfaceTextureWithBitmap(anw, bitmap)) return false; m_hasValidTexture = true; return true; }
PassRefPtr<Image> ImageBuffer::copyImage() const { ASSERT(context()); SkCanvas* canvas = imageBufferCanvas(this); if (!canvas) return 0; SkDevice* device = canvas->getDevice(); const SkBitmap& orig = device->accessBitmap(false); SkBitmap copy; if (PlatformBridge::canSatisfyMemoryAllocation(orig.getSize())) orig.copyTo(©, orig.config()); SkBitmapRef* ref = new SkBitmapRef(copy); RefPtr<Image> image = BitmapImage::create(ref, 0); ref->unref(); return image; }
String ImageBuffer::toDataURL(const String&, const double*) const { // Encode the image into a vector. SkDynamicMemoryWStream pngStream; const SkBitmap& dst = imageBufferCanvas(this)->getDevice()->accessBitmap(true); SkImageEncoder::EncodeStream(&pngStream, dst, SkImageEncoder::kPNG_Type, 100); // Convert it into base64. Vector<char> pngEncodedData; SkData* streamData = pngStream.copyToData(); pngEncodedData.append((char*)streamData->data(), streamData->size()); streamData->unref(); Vector<char> base64EncodedData; base64Encode(pngEncodedData, base64EncodedData); // Append with a \0 so that it's a valid string. base64EncodedData.append('\0'); // And the resulting string. return String::format("data:image/png;base64,%s", base64EncodedData.data()); }
String ImageBuffer::toDataURL(const String& mimeType, const double* quality) const { ASSERT(context() && context()->platformContext()); // Request for canvas bitmap; conversion required. if (context()->platformContext()->isRecording()) context()->platformContext()->convertToNonRecording(); // CAPPFIX_WEB_WEBGL SkCanvas* canvas = imageBufferCanvas(this); // CAPPFIX_WEB_WEBGL_END SkDevice* device = canvas->getDevice(); SkBitmap bitmap = device->accessBitmap(false); // if we can't see the pixels directly, call readPixels() to get a copy. // this could happen if the device is backed by a GPU. bitmap.lockPixels(); // balanced by our destructor, or explicitly if getPixels() fails if (!bitmap.getPixels()) { bitmap.unlockPixels(); SkIRect bounds = SkIRect::MakeWH(device->width(), device->height()); if (!canvas->readPixels(bounds, &bitmap)) return "data:,"; } return ImageToDataURL(bitmap, mimeType, quality); }
PassRefPtr<ByteArray> ImageBuffer::getUnmultipliedImageData(const IntRect& rect) const { ASSERT(context() && context()->platformContext()); // Request for canvas bitmap; conversion required. if (context()->platformContext()->isRecording()) context()->platformContext()->convertToNonRecording(); GraphicsContext* gc = this->context(); if (!gc) { return 0; } const SkBitmap& src = imageBufferCanvas(this)->getDevice()->accessBitmap(false); SkAutoLockPixels alp(src); if (!src.getPixels()) { return 0; } RefPtr<ByteArray> result = ByteArray::create(rect.width() * rect.height() * 4); unsigned char* data = result->data(); if (rect.x() < 0 || rect.y() < 0 || rect.maxX() > m_size.width() || rect.maxY() > m_size.height()) memset(data, 0, result->length()); int originx = rect.x(); int destx = 0; if (originx < 0) { destx = -originx; originx = 0; } int endx = rect.x() + rect.width(); if (endx > m_size.width()) endx = m_size.width(); int numColumns = endx - originx; int originy = rect.y(); int desty = 0; if (originy < 0) { desty = -originy; originy = 0; } int endy = rect.y() + rect.height(); if (endy > m_size.height()) endy = m_size.height(); int numRows = endy - originy; unsigned srcPixelsPerRow = src.rowBytesAsPixels(); unsigned destBytesPerRow = 4 * rect.width(); const SkPMColor* srcRows = src.getAddr32(originx, originy); unsigned char* destRows = data + desty * destBytesPerRow + destx * 4; for (int y = 0; y < numRows; ++y) { for (int x = 0; x < numColumns; x++) { // ugh, it appears they want unpremultiplied pixels SkColor c = SkUnPreMultiply::PMColorToColor(srcRows[x]); int basex = x * 4; destRows[basex + 0] = SkColorGetR(c); destRows[basex + 1] = SkColorGetG(c); destRows[basex + 2] = SkColorGetB(c); destRows[basex + 3] = SkColorGetA(c); } srcRows += srcPixelsPerRow; destRows += destBytesPerRow; } return result.release(); }