QPixmap Image::pixBlurredNoCache(int32 w, int32 h) const { return pixNoCache(w, h); restore(); loaded(); const QPixmap &p(pixData()); if (p.isNull()) return blank()->pix(); QImage img; if (h <= 0) { img = p.toImage().scaledToWidth(w, Qt::SmoothTransformation); } else { img = p.toImage().scaled(w, h, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); } QImage::Format fmt = img.format(); if (fmt != QImage::Format_RGB32 && fmt != QImage::Format_ARGB32 && fmt != QImage::Format_ARGB32_Premultiplied) { QImage tmp(img.width(), img.height(), QImage::Format_ARGB32); { QPainter p(&tmp); p.drawImage(0, 0, img); } img = tmp; } QImage fromimg = img; uchar *bits = img.bits(); const uchar *from = fromimg.bits(); if (bits && from) { int width = img.width(), height = img.height(); for (int i = 0; i < width; ++i) { for (int j = 0; j < height; ++j) { uint32 a = 0, b = 0, c = 0; for (int index = i - 32; index < i + 32; ++index) { int fullindex = 4 * (j * width + ((index < 0) ? 0 : (index >= width ? (width - 1) : index))), coef = 4; a += from[fullindex + 1] * coef; b += from[fullindex + 2] * coef; c += from[fullindex + 3] * coef; } int fullindex = 4 * (j * width + i); bits[fullindex + 1] = uchar(a >> 8); bits[fullindex + 2] = uchar(b >> 8); bits[fullindex + 3] = uchar(c >> 8); } } for (int i = 0; i < width; ++i) { for (int j = 0; j < height; ++j) { uint32 a = 0, b = 0, c = 0; for (int index = j - 32; index < j + 32; ++index) { int fullindex = 4 * (((index < 0) ? 0 : (index >= height ? (height - 1) : index)) * width + i), coef = 4; a += from[fullindex + 1] * coef; b += from[fullindex + 2] * coef; c += from[fullindex + 3] * coef; } int fullindex = 4 * (j * width + i); bits[fullindex + 1] = uchar(a >> 8); bits[fullindex + 2] = uchar(b >> 8); bits[fullindex + 3] = uchar(c >> 8); } } }
void HistoryPhoto::validateGroupedCache( const QRect &geometry, RectParts corners, not_null<uint64*> cacheKey, not_null<QPixmap*> cache) const { using Option = Images::Option; const auto loaded = _data->loaded(); const auto loadLevel = loaded ? 2 : (_data->thumbnailInline() || _data->thumbnail()->loaded() || _data->thumbnailSmall()->loaded()) ? 1 : 0; const auto width = geometry.width(); const auto height = geometry.height(); const auto options = Option::Smooth | Option::RoundedLarge | (loaded ? Option::None : Option::Blurred) | ((corners & RectPart::TopLeft) ? Option::RoundedTopLeft : Option::None) | ((corners & RectPart::TopRight) ? Option::RoundedTopRight : Option::None) | ((corners & RectPart::BottomLeft) ? Option::RoundedBottomLeft : Option::None) | ((corners & RectPart::BottomRight) ? Option::RoundedBottomRight : Option::None); const auto key = (uint64(width) << 48) | (uint64(height) << 32) | (uint64(options) << 16) | (uint64(loadLevel)); if (*cacheKey == key) { return; } const auto originalWidth = ConvertScale(_data->width()); const auto originalHeight = ConvertScale(_data->height()); const auto pixSize = Ui::GetImageScaleSizeForGeometry( { originalWidth, originalHeight }, { width, height }); const auto pixWidth = pixSize.width() * cIntRetinaFactor(); const auto pixHeight = pixSize.height() * cIntRetinaFactor(); const auto image = loaded ? _data->large().get() : _data->thumbnail()->loaded() ? _data->thumbnail().get() : _data->thumbnailSmall()->loaded() ? _data->thumbnailSmall().get() : _data->thumbnailInline() ? _data->thumbnailInline() : Image::BlankMedia().get(); *cacheKey = key; *cache = image->pixNoCache(_realParent->fullId(), pixWidth, pixHeight, options, width, height); }
void HistoryVideo::validateGroupedCache( const QRect &geometry, RectParts corners, not_null<uint64*> cacheKey, not_null<QPixmap*> cache) const { using Option = Images::Option; const auto good = _data->goodThumbnail(); const auto useGood = (good && good->loaded()); const auto image = useGood ? good : _data->thumb.get(); if (good && !useGood) { good->load({}); } const auto loaded = useGood ? true : _data->thumb->loaded(); const auto loadLevel = loaded ? 1 : 0; const auto width = geometry.width(); const auto height = geometry.height(); const auto options = Option::Smooth | Option::RoundedLarge | (useGood ? Option(0) : Option::Blurred) | ((corners & RectPart::TopLeft) ? Option::RoundedTopLeft : Option::None) | ((corners & RectPart::TopRight) ? Option::RoundedTopRight : Option::None) | ((corners & RectPart::BottomLeft) ? Option::RoundedBottomLeft : Option::None) | ((corners & RectPart::BottomRight) ? Option::RoundedBottomRight : Option::None); const auto key = (uint64(width) << 48) | (uint64(height) << 32) | (uint64(options) << 16) | (uint64(loadLevel)); if (*cacheKey == key) { return; } const auto originalWidth = ConvertScale(_data->thumb->width()); const auto originalHeight = ConvertScale(_data->thumb->height()); const auto pixSize = Ui::GetImageScaleSizeForGeometry( { originalWidth, originalHeight }, { width, height }); const auto pixWidth = pixSize.width() * cIntRetinaFactor(); const auto pixHeight = pixSize.height() * cIntRetinaFactor(); *cacheKey = key; *cache = image->pixNoCache(_realParent->fullId(), pixWidth, pixHeight, options, width, height); }
const QPixmap &Image::pix(int32 w, int32 h) const { restore(); checkload(); if (w <= 0 || !width() || !height()) { w = width() * cIntRetinaFactor(); } else if (cRetina()) { w *= cIntRetinaFactor(); h *= cIntRetinaFactor(); } uint64 k = (uint64(w) << 32) | uint64(h); Sizes::const_iterator i = _sizesCache.constFind(k); if (i == _sizesCache.cend()) { QPixmap p(pixNoCache(w, h, true)); if (cRetina()) p.setDevicePixelRatio(cRetinaFactor()); i = _sizesCache.insert(k, p); if (!p.isNull()) { globalAquiredSize += int64(p.width()) * p.height() * 4; } } return i.value(); }