#pragma once #include #include #include #include #include #include namespace core { namespace image_decode { /// 提高 Qt6 解码像素上限,避免大图被 reader 直接拒绝(单位 MB) inline void prepareLargeImageReader() { #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) QImageReader::setAllocationLimit(4096); #endif } /// 裁剪对话框等「仅预览」场景:像素上限(libvips 缩略与 Qt 回退共用) [[maybe_unused]] constexpr qint64 kPreviewMaxPixels = 16LL * 1000 * 1000; /// 编辑器 / 帧图替换:缩略像素上限(libvips 与 Qt 回退共用) [[maybe_unused]] constexpr qint64 kWorkspaceMaxPixels = 48LL * 1000 * 1000; /// 在 read() 前调用:若像素数超过 maxPixels,则 setScaledSize 按比例缩小(不解码全图) inline void downscaleReaderIfExceeds(QImageReader& reader, qint64 maxPixels) { const QSize sz = reader.size(); if (!sz.isValid() || sz.width() <= 0 || sz.height() <= 0) { return; } const qint64 pixels = qint64(sz.width()) * qint64(sz.height()); if (pixels <= maxPixels) { return; } const double s = std::sqrt(double(maxPixels) / double(pixels)); const int nw = std::max(1, int(std::lround(sz.width() * s))); const int nh = std::max(1, int(std::lround(sz.height() * s))); reader.setScaledSize(QSize(nw, nh)); } /// 将 rect 从 fromSize 坐标系线性映射到 toSize(例如预览图上的选区 → 原图逻辑像素) inline QRect mapRectBetweenSizes(const QRect& rect, const QSize& fromSize, const QSize& toSize) { if (!rect.isValid() || fromSize.width() <= 0 || fromSize.height() <= 0 || toSize.width() <= 0 || toSize.height() <= 0) { return {}; } const qreal sx = qreal(toSize.width()) / qreal(fromSize.width()); const qreal sy = qreal(toSize.height()) / qreal(fromSize.height()); const int x0 = int(std::floor(qreal(rect.left()) * sx)); const int y0 = int(std::floor(qreal(rect.top()) * sy)); const int x1 = int(std::ceil(qreal(rect.right() + 1) * sx)); const int y1 = int(std::ceil(qreal(rect.bottom() + 1) * sy)); QRect out(x0, y0, x1 - x0, y1 - y0); return out.normalized().intersected(QRect(0, 0, toSize.width(), toSize.height())); } } // namespace image_decode } // namespace core