Qt源码分析--QImage(7)

59 篇文章 1 订阅
37 篇文章 1 订阅

1.QImage scaledToWidth(int w, Qt::TransformationMode mode = Qt::FastTransformation) const;

/*!
    \fn QImage QImage::scaledToWidth(int width, Qt::TransformationMode mode) const
    Returns a scaled copy of the image. The returned image is scaled
    to the given \a width using the specified transformation \a
    mode.
    This function automatically calculates the height of the image so
    that its aspect ratio is preserved.
    If the given \a width is 0 or negative, a null image is returned.
    \sa {QImage#Image Transformations}{Image Transformations}
*/
QImage QImage::scaledToWidth(int w, Qt::TransformationMode mode) const
{
    if (!d) {
        qWarning("QImage::scaleWidth: Image is a null image");
        return QImage();
    }
    if (w <= 0)
        return QImage();
    Q_TRACE_SCOPE(QImage_scaledToWidth, w, mode);
    qreal factor = (qreal) w / width();
    QTransform wm = QTransform::fromScale(factor, factor);
    return transformed(wm, mode);
}

QTransform QTransform::fromScale(qreal sx, qreal sy)
{
#ifndef QT_NO_DEBUG
    if (qIsNaN(sx) | qIsNaN(sy)) {
        nanWarning("fromScale");
        return QTransform();
}
#endif
    QTransform transform(sx, 0, 0, 0, sy, 0, 0, 0, 1);
    if (sx == 1. && sy == 1.)
        transform.m_type = TxNone;
    else
        transform.m_type = TxScale;
    transform.m_dirty = TxNone;
    return transform;
}

QTransform(qreal h11, qreal h12, qreal h13,
               qreal h21, qreal h22, qreal h23,
               qreal h31, qreal h32, qreal h33)
        : m_matrix{ {h11, h12, h13}, {h21, h22, h23}, {h31, h32, h33} }
        , m_type(TxNone)
        , m_dirty(TxProject) {}


QImage QImage::transformed(const QTransform &matrix, Qt::TransformationMode mode ) const
{
    if (!d)
        return QImage();
    Q_TRACE_SCOPE(QImage_transformed, matrix, mode);
    // source image data
    const int ws = width();
    const int hs = height();
    // target image data
    int wd;
    int hd;
    // compute size of target image
    QTransform mat = trueMatrix(matrix, ws, hs);
    bool complex_xform = false;
    bool scale_xform = false;
    bool nonpaintable_scale_xform = false;
    if (mat.type() <= QTransform::TxScale) {
        if (mat.type() == QTransform::TxNone) // identity matrix
            return *this;
        else if (mat.m11() == -1. && mat.m22() == -1.)
            return rotated180(*this);
        if (mode == Qt::FastTransformation) {
            hd = qRound(qAbs(mat.m22()) * hs);
            wd = qRound(qAbs(mat.m11()) * ws);
        } else {
            hd = int(qAbs(mat.m22()) * hs + 0.9999);
            wd = int(qAbs(mat.m11()) * ws + 0.9999);
        }
        scale_xform = true;
        // The paint-based scaling is only bilinear, and has problems
        // with scaling smoothly more than 2x down.
        if (hd * 2 < hs || wd * 2 < ws)
            nonpaintable_scale_xform = true;
    } else {
        if (mat.type() <= QTransform::TxRotate && mat.m11() == 0 && mat.m22() == 0) {
            if (mat.m12() == 1. && mat.m21() == -1.)
                return rotated90(*this);
            else if (mat.m12() == -1. && mat.m21() == 1.)
                return rotated270(*this);
        }
        QPolygonF a(QRectF(0, 0, ws, hs));
        a = mat.map(a);
        QRect r = a.boundingRect().toAlignedRect();
        wd = r.width();
        hd = r.height();
        complex_xform = true;
    }
    if (wd == 0 || hd == 0)
        return QImage();
    if (scale_xform && mode == Qt::SmoothTransformation) {
        switch (format()) {
        case QImage::Format_RGB32:
        case QImage::Format_ARGB32_Premultiplied:
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
        case QImage::Format_RGBX8888:
#endif
        case QImage::Format_RGBA8888_Premultiplied:
#if QT_CONFIG(raster_64bit)
        case QImage::Format_RGBX64:
        case QImage::Format_RGBA64_Premultiplied:
#endif
            // Use smoothScaled for scaling when we can do so without conversion.
            if (mat.m11() > 0.0F && mat.m22() > 0.0F)
                return smoothScaled(wd, hd);
            break;
        default:
            break;
        }
        // Otherwise only use it when the scaling factor demands it, or the image is large enough to scale multi-threaded
        if (nonpaintable_scale_xform
#if QT_CONFIG(thread) && !defined(Q_OS_WASM)
            || (ws * hs) >= (1<<20)
#endif
            ) {
            if (mat.m11() < 0.0F && mat.m22() < 0.0F) { // horizontal/vertical flip
                return smoothScaled(wd, hd).mirrored(true, true).convertToFormat(format());
            } else if (mat.m11() < 0.0F) { // horizontal flip
                return smoothScaled(wd, hd).mirrored(true, false).convertToFormat(format());
            } else if (mat.m22() < 0.0F) { // vertical flip
                return smoothScaled(wd, hd).mirrored(false, true).convertToFormat(format());
            } else { // no flipping
                return smoothScaled(wd, hd).convertToFormat(format());
            }
        }
    }
    int bpp = depth();
    qsizetype sbpl = bytesPerLine();
    const uchar *sptr = bits();
    QImage::Format target_format = d->format;
    if (complex_xform || mode == Qt::SmoothTransformation) {
        if (d->format < QImage::Format_RGB32 || (!hasAlphaChannel() && complex_xform)) {
            target_format = qt_alphaVersion(d->format);
        }
    }
    QImage dImage(wd, hd, target_format);
    QIMAGE_SANITYCHECK_MEMORY(dImage);
    if (target_format == QImage::Format_MonoLSB
        || target_format == QImage::Format_Mono
        || target_format == QImage::Format_Indexed8) {
        dImage.d->colortable = d->colortable;
        dImage.d->has_alpha_clut = d->has_alpha_clut | complex_xform;
    }
    // initizialize the data
    if (target_format == QImage::Format_Indexed8) {
        if (dImage.d->colortable.size() < 256) {
            // colors are left in the color table, so pick that one as transparent
            dImage.d->colortable.append(0x0);
            memset(dImage.bits(), dImage.d->colortable.size() - 1, dImage.d->nbytes);
        } else {
            memset(dImage.bits(), 0, dImage.d->nbytes);
        }
    } else
        memset(dImage.bits(), 0x00, dImage.d->nbytes);
    if (target_format >= QImage::Format_RGB32) {
        // Prevent QPainter from applying devicePixelRatio corrections
        const QImage sImage = (devicePixelRatio() != 1) ? QImage(constBits(), width(), height(), format()) : *this;
        Q_ASSERT(sImage.devicePixelRatio() == 1);
        Q_ASSERT(sImage.devicePixelRatio() == dImage.devicePixelRatio());
        QPainter p(&dImage);
        if (mode == Qt::SmoothTransformation) {
            p.setRenderHint(QPainter::Antialiasing);
            p.setRenderHint(QPainter::SmoothPixmapTransform);
        }
        p.setTransform(mat);
        p.drawImage(QPoint(0, 0), sImage);
    } else {
        bool invertible;
        mat = mat.inverted(&invertible);                // invert matrix
        if (!invertible)        // error, return null image
            return QImage();
        // create target image (some of the code is from QImage::copy())
        int type = format() == Format_Mono ? QT_XFORM_TYPE_MSBFIRST : QT_XFORM_TYPE_LSBFIRST;
        qsizetype dbpl = dImage.bytesPerLine();
        qt_xForm_helper(mat, 0, type, bpp, dImage.bits(), dbpl, 0, hd, sptr, sbpl, ws, hs);
    }
    copyMetadata(dImage.d, d);
    return dImage;
}

根据输入的w参数,计算缩放因子factor。

把facotor作为参数,调用QTransform::fromScale, 该函数返回一个QTransform对象。

在QTransform的构造函数里,创建了一个矩阵,用于保存缩放参数。

之后,调用transformed函数进行转换。

2.QImage scaledToHeight(int h, Qt::TransformationMode mode = Qt::FastTransformation) const;

/*!
    \fn QImage QImage::scaledToHeight(int height, Qt::TransformationMode mode) const
    Returns a scaled copy of the image. The returned image is scaled
    to the given \a height using the specified transformation \a
    mode.
    This function automatically calculates the width of the image so that
    the ratio of the image is preserved.
    If the given \a height is 0 or negative, a null image is returned.
    \sa {QImage#Image Transformations}{Image Transformations}
*/
QImage QImage::scaledToHeight(int h, Qt::TransformationMode mode) const
{
    if (!d) {
        qWarning("QImage::scaleHeight: Image is a null image");
        return QImage();
    }
    if (h <= 0)
        return QImage();
    Q_TRACE_SCOPE(QImage_scaledToHeight, h, mode);
    qreal factor = (qreal) h / height();
    QTransform wm = QTransform::fromScale(factor, factor);
    return transformed(wm, mode);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天天进步2015

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值