Qimages container



我正在寻找像QSprite这样的类,它负责从源文件中读取像素图,将源图像拆分为图像序列,并按索引返回子图像。

像这样:

class QSprite2
{
    bool load(QUrl url, QSize frameSize);
    QImage getFrame(int index);
};

有没有办法使用现有类获得描述的功能。或者也许我必须自己实现描述逻辑?

您可以使用

QQuickImageProvider .这是我写的一个类,它做了类似的事情:

SpriteImageProvider.h

#ifndef SPRITEIMAGEPROVIDER_H
#define SPRITEIMAGEPROVIDER_H
#include <QHash>
#include <QImage>
#include <QString>
#include <QQuickImageProvider>
#include "IsleGlobal.h"
class ISLE_EXPORT SpriteImageProvider : public QQuickImageProvider
{
public:
    SpriteImageProvider();
    QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize) override;
private:
    int parseFrameIndex(const QString &frameIndexStr) const;
    int parseFrameWidth(const QString &frameWidthStr) const;
    int parseFrameHeight(const QString &frameHeightStr) const;
    QHash<QString, QImage> mImages;
};
#endif // SPRITEIMAGEPROVIDER_H

SpriteImageProvider.cpp

#include "SpriteImageProvider.h"
#include <QImage>
#include <QDebug>
SpriteImageProvider::SpriteImageProvider() :
    QQuickImageProvider(QQmlImageProviderBase::Image)
{
}
static const QRgb whiteRgba = qRgba(255, 255, 255, 255);
static const QRgb magentaRgba = qRgba(255, 0, 255, 255);
static const QRgb transparentRgba = qRgba(0, 0, 0, 0);
QImage SpriteImageProvider::requestImage(const QString &id, QSize *size, const QSize &)
{
    QStringList args = id.split(QLatin1String(","));
    if (args.length() < 1) {
        qWarning() << "Must pass at least the file name as arguments for SpriteImageProvider source";
        return QImage();
    } else if (args.length() != 1 && args.length() != 2 && args.length() != 4) {
        qWarning() << "Must pass either (fileName), (fileName, frameIndex) or"
                   << "(fileName, frameWidth, frameHeight, frameIndex) as arguments for SpriteImageProvider source";
        return QImage();
    }
    const QString imageFilename = ":/" + args.first();
    int frameIndex = -2;
    int frameWidth = -2;
    int frameHeight = -2;
    if (args.length() > 1) {
        frameIndex = parseFrameIndex(args.last());
        if (frameIndex == -1)
            return QImage();
    }
    if (args.length() == 4) {
        frameWidth = parseFrameIndex(args.at(1));
        if (frameWidth == -1)
            return QImage();
        frameHeight = parseFrameIndex(args.at(2));
        if (frameHeight == -1)
            return QImage();
    }
    QHash<QString, QImage>::const_iterator it = mImages.find(imageFilename);
    if (it == mImages.end()) {
        QImage image(imageFilename);
        if (image.isNull()) {
            qWarning() << "Failed to load image at" << imageFilename;
            return image;
        }
        // TODO: is there a better way of doing this?
        QImage alphaImage = image;
        for (int y = 0; y < alphaImage.height(); ++y) {
            for (int x = 0; x < alphaImage.width(); ++x) {
                const QRgb pixelRgb = alphaImage.pixel(x, y);
                if (pixelRgb == whiteRgba || pixelRgb == magentaRgba)
                    alphaImage.setPixel(x, y, transparentRgba);
            }
        }
        mImages.insert(imageFilename, alphaImage);
        it = mImages.find(imageFilename);
    }
    if (frameWidth == -2 || frameHeight == -2) {
        if (frameIndex == -2) {
            // Use the whole image.
            frameWidth = it.value().width();
            frameHeight = it.value().height();
            frameIndex = 0;
        } else {
            frameWidth = 64;
            frameHeight = 64;
        }
    }
    // Copy an individual frame out of the larger image.
    const int framesWide = it.value().width() / frameWidth;
    const QRect subRect((frameIndex % framesWide) * frameWidth,
                        (frameIndex / framesWide) * frameHeight,
                        frameWidth,
                        frameHeight);
//    qDebug() << "id" << id;
//    qDebug() << "framesWide" << framesWide;
//    qDebug() << "subRect" << subRect;
    const QImage frameImage = it.value().copy(subRect);
    *size = frameImage.size();
    return frameImage;
}

int SpriteImageProvider::parseFrameIndex(const QString &frameIndexStr) const
{
    bool convertedToIntSuccessfully = false;
    const int frameIndex = frameIndexStr.toInt(&convertedToIntSuccessfully);
    if (!convertedToIntSuccessfully) {
        qWarning() << "Failed to convert frame index" << frameIndexStr << "to an int";
        return -1;
    }
    return frameIndex;
}
int SpriteImageProvider::parseFrameWidth(const QString &frameWidthStr) const
{
    bool convertedToIntSuccessfully = false;
    const int frameWidth = frameWidthStr.toInt(&convertedToIntSuccessfully);
    if (!convertedToIntSuccessfully) {
        qWarning() << "Failed to convert frame width" << frameWidthStr << "to an int";
        return -1;
    }
    return frameWidth;
}
int SpriteImageProvider::parseFrameHeight(const QString &frameHeightStr) const
{
    bool convertedToIntSuccessfully = false;
    const int frameHeight = frameHeightStr.toInt(&convertedToIntSuccessfully);
    if (!convertedToIntSuccessfully) {
        qWarning() << "Failed to convert frame height" << frameHeightStr << "to an int";
        return -1;
    }
    return frameHeight;
}

它还支持"alpha键" - 源图像中的白色和洋红色像素将转换为透明像素。

它是在QML引擎中注册的,如下所示:

mEngine->addImageProvider("sprite", new SpriteImageProvider);

并在 QML 中使用如下:

import QtQuick 2.5
Image {
     source: qsTr('image://sprite/sprites/hugh.png,%1').arg(_sceneItemComponent ? _sceneItemComponent.facingDirection : 0)
}

其中facingDirection是要使用的帧索引。您还可以传递.cpp文件中提到的其他参数。

相关内容

  • 没有找到相关文章

最新更新