Image Image::convertedToFormat (PixelFormat newFormat) const { if (image == nullptr || newFormat == image->pixelFormat) return *this; const int w = image->width, h = image->height; const ScopedPointer<ImageType> type (image->createType()); Image newImage (type->create (newFormat, w, h, false)); if (newFormat == SingleChannel) { if (! hasAlphaChannel()) { newImage.clear (getBounds(), Colours::black); } else { const BitmapData destData (newImage, 0, 0, w, h, BitmapData::writeOnly); const BitmapData srcData (*this, 0, 0, w, h); for (int y = 0; y < h; ++y) { const PixelARGB* const src = (const PixelARGB*) srcData.getLinePointer (y); uint8* const dst = destData.getLinePointer (y); for (int x = 0; x < w; ++x) dst[x] = src[x].getAlpha(); } } } else if (image->pixelFormat == SingleChannel && newFormat == Image::ARGB) { const BitmapData destData (newImage, 0, 0, w, h, BitmapData::writeOnly); const BitmapData srcData (*this, 0, 0, w, h); for (int y = 0; y < h; ++y) { const PixelAlpha* const src = (const PixelAlpha*) srcData.getLinePointer (y); PixelARGB* const dst = (PixelARGB*) destData.getLinePointer (y); for (int x = 0; x < w; ++x) dst[x].set (src[x]); } } else { if (hasAlphaChannel()) newImage.clear (getBounds()); Graphics g (newImage); g.drawImageAt (*this, 0, 0); } return newImage; }
void Image::multiplyAllAlphas (const float amountToMultiplyBy) { jassert (hasAlphaChannel()); const BitmapData destData (*this, 0, 0, getWidth(), getHeight(), BitmapData::readWrite); performPixelOp (destData, AlphaMultiplyOp (amountToMultiplyBy)); }
QPaintEngine* QX11GLPixmapData::paintEngine() const { // We need to create the context before beginPaint - do it here: if (!ctx) { ctx = new QGLContext(glFormat()); if (ctx->d_func()->eglContext == 0) ctx->d_func()->eglContext = new QEglContext(); ctx->d_func()->eglContext->openDisplay(0); // ;-) ctx->d_func()->eglContext->setApi(QEgl::OpenGL); ctx->d_func()->eglContext->setContext(hasAlphaChannel() ? qPixmapARGBSharedEglContext : qPixmapRGBSharedEglContext); } if (!qt_gl2_engine_for_pixmaps) qt_gl2_engine_for_pixmaps = new QGL2PaintEngineEx(); // Support multiple painters on multiple pixmaps simultaniously if (qt_gl2_engine_for_pixmaps->isActive()) { qWarning("Pixmap paint engine already active"); QPaintEngine* engine = new QGL2PaintEngineEx(); engine->setAutoDestruct(true); return engine; } return qt_gl2_engine_for_pixmaps; }
QImage QDirectFBPixmapData::toImage() const { if (!dfbSurface) return QImage(); #if 0 // In later versions of DirectFB one can set a flag to tell // DirectFB not to move the surface to videomemory. When that // happens we can use this (hopefully faster) codepath #ifndef QT_NO_DIRECTFB_PREALLOCATED QImage ret(w, h, QDirectFBScreen::getImageFormat(dfbSurface)); if (IDirectFBSurface *imgSurface = screen->createDFBSurface(ret, QDirectFBScreen::DontTrackSurface)) { if (hasAlphaChannel()) { imgSurface->SetBlittingFlags(imgSurface, DSBLIT_BLEND_ALPHACHANNEL); imgSurface->Clear(imgSurface, 0, 0, 0, 0); } else { imgSurface->SetBlittingFlags(imgSurface, DSBLIT_NOFX); } imgSurface->Blit(imgSurface, dfbSurface, 0, 0, 0); #if (Q_DIRECTFB_VERSION >= 0x010000) imgSurface->ReleaseSource(imgSurface); #endif imgSurface->Release(imgSurface); return ret; } #endif #endif QDirectFBPixmapData *that = const_cast<QDirectFBPixmapData*>(this); const QImage *img = that->buffer(); return img->copy(); }
void QBlittablePlatformPixmap::fill(const QColor &color) { if (blittable()->capabilities() & QBlittable::AlphaFillRectCapability) { blittable()->unlock(); blittable()->alphaFillRect(QRectF(0,0,w,h),color,QPainter::CompositionMode_Source); } else if (color.alpha() == 255 && blittable()->capabilities() & QBlittable::SolidRectCapability) { blittable()->unlock(); blittable()->fillRect(QRectF(0,0,w,h),color); } else { // Need to be backed with an alpha channel now. It would be nice // if we could just change the format, e.g. when going from // RGB32 -> ARGB8888. if (color.alpha() != 255 && !hasAlphaChannel()) { m_blittable.reset(0); m_engine.reset(0); m_alpha = true; } uint pixel = PREMUL(color.rgba()); const QPixelLayout *layout = &qPixelLayouts[blittable()->lock()->format()]; Q_ASSERT(layout->convertFromARGB32PM); layout->convertFromARGB32PM(&pixel, &pixel, 1, layout, 0); //so premultiplied formats are supported and ARGB32 and RGB32 blittable()->lock()->fill(pixel); } }
Image Image::convertedToFormat (PixelFormat newFormat) const { if (image == nullptr || newFormat == image->format) return *this; const int w = image->width, h = image->height; Image newImage (newFormat, w, h, false, image->getType()); if (newFormat == SingleChannel) { if (! hasAlphaChannel()) { newImage.clear (getBounds(), Colours::black); } else { const BitmapData destData (newImage, 0, 0, w, h, BitmapData::writeOnly); const BitmapData srcData (*this, 0, 0, w, h); for (int y = 0; y < h; ++y) { const PixelARGB* src = (const PixelARGB*) srcData.getLinePointer(y); uint8* dst = destData.getLinePointer (y); for (int x = w; --x >= 0;) { *dst++ = src->getAlpha(); ++src; } } } } else { if (hasAlphaChannel()) newImage.clear (getBounds()); Graphics g (newImage); g.drawImageAt (*this, 0, 0); } return newImage; }
void Image::multiplyAlphaAt (const int x, const int y, const float multiplier) { if (isPositiveAndBelow (x, getWidth()) && isPositiveAndBelow (y, getHeight()) && hasAlphaChannel()) { const BitmapData destData (*this, x, y, 1, 1, BitmapData::readWrite); if (isARGB()) ((PixelARGB*) destData.data)->multiplyAlpha (multiplier); else *(destData.data) = (uint8) (*(destData.data) * multiplier); } }
Image Image::rescaled (const int newWidth, const int newHeight, const Graphics::ResamplingQuality quality) const { if (image == nullptr || (image->width == newWidth && image->height == newHeight)) return *this; Image newImage (image->format, newWidth, newHeight, hasAlphaChannel(), image->getType()); Graphics g (newImage); g.setImageResamplingQuality (quality); g.drawImage (*this, 0, 0, newWidth, newHeight, 0, 0, image->width, image->height, false); return newImage; }
Image Image::rescaled (const int newWidth, const int newHeight, const Graphics::ResamplingQuality quality) const { if (image == nullptr || (image->width == newWidth && image->height == newHeight)) return *this; const ScopedPointer<ImageType> type (image->createType()); Image newImage (type->create (image->pixelFormat, newWidth, newHeight, hasAlphaChannel())); Graphics g (newImage); g.setImageResamplingQuality (quality); g.drawImage (*this, 0, 0, newWidth, newHeight, 0, 0, image->width, image->height, false); return newImage; }
void QDirectFBPixmapData::fill(const QColor &color) { if (!serialNumber()) return; Q_ASSERT(surface); if (color.alpha() < 255 && !hasAlphaChannel()) { // convert to surface supporting alpha channel DFBSurfacePixelFormat format; surface->GetPixelFormat(surface, &format); switch (format) { case DSPF_YUY2: case DSPF_UYVY: format = DSPF_AYUV; break; #if (Q_DIRECTFB_VERSION >= 0x010100) case DSPF_RGB444: format = DSPF_ARGB4444; break; case DSPF_RGB555: #endif case DSPF_RGB18: format = DSPF_ARGB6666; break; default: format = DSPF_ARGB; break; } DFBSurfaceDescription description; description.flags = DFBSurfaceDescriptionFlags(DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT); surface->GetSize(surface, &description.width, &description.height); description.pixelformat = format; surface->Release(surface); // release old surface IDirectFB *fb = QDirectFBScreen::instance()->dfb(); DFBResult result = fb->CreateSurface(fb, &description, &surface); if (result != DFB_OK) { DirectFBError("QDirectFBPixmapData::fill()", result); setSerialNumber(0); return; } } surface->Clear(surface, color.red(), color.green(), color.blue(), color.alpha()); }
void Image::createSolidAreaMask (RectangleList& result, const float alphaThreshold) const { if (hasAlphaChannel()) { const uint8 threshold = (uint8) jlimit (0, 255, roundToInt (alphaThreshold * 255.0f)); SparseSet<int> pixelsOnRow; const BitmapData srcData (*this, 0, 0, getWidth(), getHeight()); for (int y = 0; y < srcData.height; ++y) { pixelsOnRow.clear(); const uint8* lineData = srcData.getLinePointer (y); if (isARGB()) { for (int x = 0; x < srcData.width; ++x) { if (((const PixelARGB*) lineData)->getAlpha() >= threshold) pixelsOnRow.addRange (Range<int> (x, x + 1)); lineData += srcData.pixelStride; } } else { for (int x = 0; x < srcData.width; ++x) { if (*lineData >= threshold) pixelsOnRow.addRange (Range<int> (x, x + 1)); lineData += srcData.pixelStride; } } for (int i = 0; i < pixelsOnRow.getNumRanges(); ++i) { const Range<int> range (pixelsOnRow.getRange (i)); result.add (Rectangle<int> (range.getStart(), y, range.getLength(), 1)); } result.consolidate(); } } else { result.add (0, 0, getWidth(), getHeight()); } }
void QBlittablePixmapData::fill(const QColor &color) { if (blittable()->capabilities() & QBlittable::AlphaFillRectCapability) { blittable()->unlock(); blittable()->alphaFillRect(QRectF(0,0,w,h),color,QPainter::CompositionMode_Source); } else if (color.alpha() == 255 && blittable()->capabilities() & QBlittable::SolidRectCapability) { blittable()->unlock(); blittable()->fillRect(QRectF(0,0,w,h),color); } else { // Need to be backed with an alpha channel now. It would be nice // if we could just change the format, e.g. when going from // RGB32 -> ARGB8888. if (color.alpha() != 255 && !hasAlphaChannel()) { m_blittable.reset(0); m_engine.reset(0); m_alpha = true; } uint pixel; switch (blittable()->lock()->format()) { case QImage::Format_ARGB32_Premultiplied: pixel = PREMUL(color.rgba()); break; case QImage::Format_ARGB8565_Premultiplied: pixel = qargb8565(color.rgba()).rawValue(); break; case QImage::Format_ARGB8555_Premultiplied: pixel = qargb8555(color.rgba()).rawValue(); break; case QImage::Format_ARGB6666_Premultiplied: pixel = qargb6666(color.rgba()).rawValue(); break; case QImage::Format_ARGB4444_Premultiplied: pixel = qargb4444(color.rgba()).rawValue(); break; default: pixel = color.rgba(); break; } //so premultiplied formats are supported and ARGB32 and RGB32 blittable()->lock()->fill(pixel); } }
void GoodThumbSource::generate(base::binary_guard &&guard) { if (!guard) { return; } const auto data = _document->data(); const auto isWallPaper = _document->isWallPaper(); auto location = _document->location().isEmpty() ? nullptr : std::make_unique<FileLocation>(_document->location()); if (data.isEmpty() && !location) { _empty = true; return; } crl::async([ =, guard = std::move(guard), location = std::move(location) ]() mutable { const auto filepath = (location && location->accessEnable()) ? location->name() : QString(); auto result = Prepare(filepath, data, isWallPaper); auto bytes = QByteArray(); if (!result.isNull()) { auto buffer = QBuffer(&bytes); const auto format = (isWallPaper && result.hasAlphaChannel()) ? "PNG" : "JPG"; result.save(&buffer, format, kGoodThumbQuality); } if (!filepath.isEmpty()) { location->accessDisable(); } const auto bytesSize = bytes.size(); ready( std::move(guard), std::move(result), bytesSize, std::move(bytes)); }); }
void Image::multiplyAllAlphas (const float amountToMultiplyBy) { if (hasAlphaChannel()) { const BitmapData destData (*this, 0, 0, getWidth(), getHeight(), BitmapData::readWrite); if (isARGB()) { for (int y = 0; y < destData.height; ++y) { uint8* p = destData.getLinePointer (y); for (int x = 0; x < destData.width; ++x) { ((PixelARGB*) p)->multiplyAlpha (amountToMultiplyBy); p += destData.pixelStride; } } } else { for (int y = 0; y < destData.height; ++y) { uint8* p = destData.getLinePointer (y); for (int x = 0; x < destData.width; ++x) { *p = (uint8) (*p * amountToMultiplyBy); p += destData.pixelStride; } } } } else { jassertfalse; // can't do this without an alpha-channel! } }