bool GraphicsContext3D::getImageData(Image* image, GC3Denum format, GC3Denum type, bool premultiplyAlpha, bool ignoreGammaAndColorProfile, Vector<uint8_t>& outputVector) { UNUSED_PARAM(ignoreGammaAndColorProfile); if (!image) return false; QImage nativeImage; // Is image already loaded? If not, load it. if (image->data()) nativeImage = QImage::fromData(reinterpret_cast<const uchar*>(image->data()->data()), image->data()->size()).convertToFormat(QImage::Format_ARGB32); else { QPixmap* nativePixmap = image->nativeImageForCurrentFrame(); nativeImage = nativePixmap->toImage().convertToFormat(QImage::Format_ARGB32); } AlphaOp neededAlphaOp = AlphaDoNothing; if (premultiplyAlpha) neededAlphaOp = AlphaDoPremultiply; unsigned int packedSize; // Output data is tightly packed (alignment == 1). if (computeImageSizeInBytes(format, type, image->width(), image->height(), 1, &packedSize, 0) != GraphicsContext3D::NO_ERROR) return false; outputVector.resize(packedSize); return packPixels(nativeImage.bits(), SourceFormatBGRA8, image->width(), image->height(), 0, format, type, neededAlphaOp, outputVector.data()); }
bool GraphicsContext3D::getImageData(Image* image, unsigned int format, unsigned int type, bool premultiplyAlpha, bool ignoreGammaAndColorProfile, Vector<uint8_t>& outputVector) { if (!image) return false; // We need this to stay in scope because the native image is just a shallow copy of the data. ImageSource decoder(premultiplyAlpha ? ImageSource::AlphaPremultiplied : ImageSource::AlphaNotPremultiplied, ignoreGammaAndColorProfile ? ImageSource::GammaAndColorProfileIgnored : ImageSource::GammaAndColorProfileApplied); AlphaOp alphaOp = AlphaDoNothing; RefPtr<cairo_surface_t> imageSurface; if (image->data()) { decoder.setData(image->data(), true); if (!decoder.frameCount() || !decoder.frameIsCompleteAtIndex(0)) return false; OwnPtr<NativeImageCairo> nativeImage = adoptPtr(decoder.createFrameAtIndex(0)); imageSurface = nativeImage->surface(); } else { imageSurface = image->nativeImageForCurrentFrame()->surface(); if (!premultiplyAlpha) alphaOp = AlphaDoUnmultiply; } if (!imageSurface) return false; int width = cairo_image_surface_get_width(imageSurface.get()); int height = cairo_image_surface_get_height(imageSurface.get()); if (!width || !height) return false; if (cairo_image_surface_get_format(imageSurface.get()) != CAIRO_FORMAT_ARGB32) return false; unsigned int srcUnpackAlignment = 1; size_t bytesPerRow = cairo_image_surface_get_stride(imageSurface.get()); size_t bitsPerPixel = 32; unsigned int padding = bytesPerRow - bitsPerPixel / 8 * width; if (padding) { srcUnpackAlignment = padding + 1; while (bytesPerRow % srcUnpackAlignment) ++srcUnpackAlignment; } unsigned int packedSize; // Output data is tightly packed (alignment == 1). if (computeImageSizeInBytes(format, type, width, height, 1, &packedSize, 0) != GraphicsContext3D::NO_ERROR) return false; outputVector.resize(packedSize); return packPixels(cairo_image_surface_get_data(imageSurface.get()), SourceFormatBGRA8, width, height, srcUnpackAlignment, format, type, alphaOp, outputVector.data()); }
bool GraphicsContext3D::packImageData( Image* image, const void* pixels, GC3Denum format, GC3Denum type, bool flipY, AlphaOp alphaOp, DataFormat sourceFormat, unsigned width, unsigned height, unsigned sourceUnpackAlignment, Vector<uint8_t>& data) { if (!pixels) return false; unsigned packedSize; // Output data is tightly packed (alignment == 1). if (computeImageSizeInBytes(format, type, width, height, 1, &packedSize, 0) != GraphicsContext3D::NO_ERROR) return false; data.resize(packedSize); if (!packPixels(reinterpret_cast<const uint8_t*>(pixels), sourceFormat, width, height, sourceUnpackAlignment, format, type, alphaOp, data.data(), flipY)) return false; if (ImageObserver* observer = image->imageObserver()) observer->didDraw(image); return true; }
bool GraphicsContext3D::extractImageData(ImageData* imageData, GC3Denum format, GC3Denum type, bool flipY, bool premultiplyAlpha, Vector<uint8_t>& data) { if (!imageData) return false; int width = imageData->width(); int height = imageData->height(); unsigned int packedSize; // Output data is tightly packed (alignment == 1). if (computeImageSizeInBytes(format, type, width, height, 1, &packedSize, 0) != GraphicsContext3D::NO_ERROR) return false; data.resize(packedSize); if (!packPixels(imageData->data()->data(), DataFormatRGBA8, width, height, 0, format, type, premultiplyAlpha ? AlphaDoPremultiply : AlphaDoNothing, data.data(), flipY)) return false; return true; }
bool GraphicsContext3D::texImage2DResourceSafe(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, GC3Dint unpackAlignment) { ASSERT(unpackAlignment == 1 || unpackAlignment == 2 || unpackAlignment == 4 || unpackAlignment == 8); std::unique_ptr<unsigned char[]> zero; if (!isResourceSafe() && width > 0 && height > 0) { unsigned int size; GC3Denum error = computeImageSizeInBytes(format, type, width, height, unpackAlignment, &size, 0); if (error != GraphicsContext3D::NO_ERROR) { synthesizeGLError(error); return false; } zero = std::make_unique<unsigned char[]>(size); if (!zero) { synthesizeGLError(GraphicsContext3D::INVALID_VALUE); return false; } memset(zero.get(), 0, size); } return texImage2D(target, level, internalformat, width, height, border, format, type, zero.get()); }