summaryrefslogtreecommitdiffstats
path: root/src/datavisualization/data
diff options
context:
space:
mode:
authorMiikka Heikkinen <miikka.heikkinen@digia.com>2014-08-25 13:16:04 +0300
committerMiikka Heikkinen <miikka.heikkinen@digia.com>2014-08-25 15:01:10 +0300
commit5a51d06ec8f0210f51e65abfde9f868ab7bfa8ef (patch)
tree2319880f2d66e5610d9d1040d886f52cada82ad8 /src/datavisualization/data
parentf9bb71fd11cce59d74e78202a1117c8abb3a2e44 (diff)
Add alpha multiplier to QCustom3DVolume api
Change-Id: I856c4166513f6d6f7b73fd52bc46d52ab1b8fdff Reviewed-by: Tomi Korpipää <tomi.korpipaa@digia.com> Reviewed-by: Mika Salmela <mika.salmela@digia.com>
Diffstat (limited to 'src/datavisualization/data')
-rw-r--r--src/datavisualization/data/customrenderitem.cpp8
-rw-r--r--src/datavisualization/data/customrenderitem_p.h12
-rw-r--r--src/datavisualization/data/qcustom3dvolume.cpp251
-rw-r--r--src/datavisualization/data/qcustom3dvolume.h10
-rw-r--r--src/datavisualization/data/qcustom3dvolume_p.h10
5 files changed, 216 insertions, 75 deletions
diff --git a/src/datavisualization/data/customrenderitem.cpp b/src/datavisualization/data/customrenderitem.cpp
index 3eb68845..c316fd38 100644
--- a/src/datavisualization/data/customrenderitem.cpp
+++ b/src/datavisualization/data/customrenderitem.cpp
@@ -36,7 +36,13 @@ CustomRenderItem::CustomRenderItem()
m_textureWidth(0),
m_textureHeight(0),
m_textureDepth(0),
- m_isVolume(false)
+ m_isVolume(false),
+ m_textureFormat(QImage::Format_ARGB32),
+ m_sliceIndexX(-1),
+ m_sliceIndexY(-1),
+ m_sliceIndexZ(-1),
+ m_alphaMultiplier(1.0f),
+ m_preserveOpacity(true)
{
}
diff --git a/src/datavisualization/data/customrenderitem_p.h b/src/datavisualization/data/customrenderitem_p.h
index e21b6f39..5428ce43 100644
--- a/src/datavisualization/data/customrenderitem_p.h
+++ b/src/datavisualization/data/customrenderitem_p.h
@@ -89,9 +89,13 @@ public:
inline void setSliceIndexX(int index) { m_sliceIndexX = index; }
inline void setSliceIndexY(int index) { m_sliceIndexY = index; }
inline void setSliceIndexZ(int index) { m_sliceIndexZ = index; }
- int sliceIndexX() const { return m_sliceIndexX; }
- int sliceIndexY() const { return m_sliceIndexY; }
- int sliceIndexZ() const { return m_sliceIndexZ; }
+ inline int sliceIndexX() const { return m_sliceIndexX; }
+ inline int sliceIndexY() const { return m_sliceIndexY; }
+ inline int sliceIndexZ() const { return m_sliceIndexZ; }
+ inline void setAlphaMultiplier(float mult) { m_alphaMultiplier = mult; }
+ inline float alphaMultiplier() const { return m_alphaMultiplier; }
+ inline void setPreserveOpacity(bool enable) { m_preserveOpacity = enable; }
+ inline bool preserveOpacity() const { return m_preserveOpacity; }
private:
Q_DISABLE_COPY(CustomRenderItem)
@@ -120,6 +124,8 @@ private:
int m_sliceIndexX;
int m_sliceIndexY;
int m_sliceIndexZ;
+ float m_alphaMultiplier;
+ bool m_preserveOpacity;
};
typedef QHash<QCustom3DItem *, CustomRenderItem *> CustomRenderItemArray;
diff --git a/src/datavisualization/data/qcustom3dvolume.cpp b/src/datavisualization/data/qcustom3dvolume.cpp
index cab79ac0..c1a77dba 100644
--- a/src/datavisualization/data/qcustom3dvolume.cpp
+++ b/src/datavisualization/data/qcustom3dvolume.cpp
@@ -112,6 +112,30 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION
*/
/*!
+ * \qmlproperty real Custom3DVolume::alphaMultiplier
+ *
+ * The alpha value of every texel of the volume texture is multiplied with this value at
+ * the render time. This can be used to introduce uniform transparency to the volume.
+ * If preserveOpacity is \c{true}, only texels with at least some transparency to begin with are
+ * affected, and fully opaque texels are not affected.
+ * The value must not be negative.
+ * Defaults to \c{1.0}.
+ *
+ * \sa preserveOpacity
+ */
+
+/*!
+ * \qmlproperty bool Custom3DVolume::preserveOpacity
+ *
+ * If this property value is \c{true}, alphaMultiplier is only applied to texels that already have
+ * some transparency. If it is \c{false}, the multiplier is applied to the alpha value of all
+ * texels.
+ * Defaults to \c{true}.
+ *
+ * \sa alphaMultiplier
+ */
+
+/*!
* Constructs QCustom3DVolume with given \a parent.
*/
QCustom3DVolume::QCustom3DVolume(QObject *parent) :
@@ -578,84 +602,72 @@ QImage::Format QCustom3DVolume::textureFormat() const
}
/*!
- * Renders the slice specified by \a index along \a axis into an image.
- * The texture format of this object is used.
+ * \property QCustom3DVolume::alphaMultiplier
*
- * \return the rendered image of the slice, or a null image if invalid index is specified.
+ * The alpha value of every texel of the volume texture is multiplied with this value at
+ * the render time. This can be used to introduce uniform transparency to the volume.
+ * If preserveOpacity is \c{true}, only texels with at least some transparency to begin with are
+ * affected, and fully opaque texels are not affected.
+ * The value must not be negative.
+ * Defaults to \c{1.0f}.
*
- * \sa textureFormat
+ * \sa preserveOpacity, textureData
*/
-QImage QCustom3DVolume::renderSlice(Qt::Axis axis, int index)
+void QCustom3DVolume::setAlphaMultiplier(float mult)
{
- if (index < 0)
- return QImage();
-
- int x;
- int y;
- if (axis == Qt::XAxis) {
- if (index >= textureWidth())
- return QImage();
- x = textureDepth();
- y = textureHeight();
- } else if (axis == Qt::YAxis) {
- if (index >= textureHeight())
- return QImage();
- x = textureWidth();
- y = textureDepth();
+ if (mult >= 0.0f) {
+ if (dptr()->m_alphaMultiplier != mult) {
+ dptr()->m_alphaMultiplier = mult;
+ dptr()->m_dirtyBitsVolume.alphaDirty = true;
+ emit alphaMultiplierChanged(mult);
+ emit dptr()->needUpdate();
+ }
} else {
- if (index >= textureDepth())
- return QImage();
- x = textureWidth();
- y = textureHeight();
+ qWarning() << __FUNCTION__ << "Attempted to set negative multiplier.";
}
+}
- int padding = 0;
- int pixelWidth = 4;
- if (textureFormat() == QImage::Format_Indexed8) {
- padding = x % 4;
- pixelWidth = 1;
- }
- QVector<uchar> data((x + padding) * y * pixelWidth);
- int frameSize = textureDataWidth() * textureHeight();
+float QCustom3DVolume::alphaMultiplier() const
+{
+ return dptrc()->m_alphaMultiplier;
+}
- int dataIndex = 0;
- if (axis == Qt::XAxis) {
- for (int i = 0; i < y; i++) {
- const uchar *p = textureData()->constData()
- + (index * pixelWidth) + (textureDataWidth() * i);
- for (int j = 0; j < x; j++) {
- data[dataIndex++] = *p;
- for (int k = 1; k < pixelWidth; k++)
- data[dataIndex++] = *(p + k);
- p += frameSize;
- }
- }
- } else if (axis == Qt::YAxis) {
- for (int i = 0; i < y; i++) {
- const uchar *p = textureData()->constData() + (index * textureDataWidth())
- + (frameSize * i);
- for (int j = 0; j < (x * pixelWidth); j++) {
- data[dataIndex++] = *p;
- p++;
- }
- }
- } else {
- for (int i = 0; i < y; i++) {
- const uchar *p = textureData()->constData() + (index * frameSize)
- + (textureDataWidth() * i);
- for (int j = 0; j < (x * pixelWidth); j++) {
- data[dataIndex++] = *p;
- p++;
- }
- }
+/*!
+ * \property QCustom3DVolume::preserveOpacity
+ *
+ * If this property value is \c{true}, alphaMultiplier is only applied to texels that already have
+ * some transparency. If it is \c{false}, the multiplier is applied to the alpha value of all
+ * texels.
+ * Defaults to \c{true}.
+ *
+ * \sa alphaMultiplier
+ */
+void QCustom3DVolume::setPreserveOpacity(bool enable)
+{
+ if (dptr()->m_preserveOpacity != enable) {
+ dptr()->m_preserveOpacity = enable;
+ dptr()->m_dirtyBitsVolume.alphaDirty = true;
+ emit preserveOpacityChanged(enable);
+ emit dptr()->needUpdate();
}
+}
- QImage image(data.constData(), x, y, x * pixelWidth, textureFormat());
- image.bits(); // Call bits() to detach the new image from local data
- if (textureFormat() == QImage::Format_Indexed8)
- image.setColorTable(colorTable());
+bool QCustom3DVolume::preserveOpacity() const
+{
+ return dptrc()->m_preserveOpacity;
+}
- return image;
+/*!
+ * Renders the slice specified by \a index along \a axis into an image.
+ * The texture format of this object is used.
+ *
+ * \return the rendered image of the slice, or a null image if invalid index is specified.
+ *
+ * \sa textureFormat
+ */
+QImage QCustom3DVolume::renderSlice(Qt::Axis axis, int index)
+{
+ return dptr()->renderSlice(axis, index);
}
/*!
@@ -683,7 +695,9 @@ QCustom3DVolumePrivate::QCustom3DVolumePrivate(QCustom3DVolume *q) :
m_textureHeight(0),
m_textureDepth(0),
m_textureFormat(QImage::Format_ARGB32),
- m_textureData(0)
+ m_textureData(0),
+ m_alphaMultiplier(1.0f),
+ m_preserveOpacity(true)
{
m_isVolumeItem = true;
m_meshFile = QStringLiteral(":/defaultMeshes/barFull");
@@ -705,7 +719,9 @@ QCustom3DVolumePrivate::QCustom3DVolumePrivate(QCustom3DVolume *q, const QVector
m_textureDepth(textureDepth),
m_textureFormat(textureFormat),
m_colorTable(colorTable),
- m_textureData(textureData)
+ m_textureData(textureData),
+ m_alphaMultiplier(1.0f),
+ m_preserveOpacity(true)
{
m_isVolumeItem = true;
m_shadowCasting = false;
@@ -738,6 +754,103 @@ void QCustom3DVolumePrivate::resetDirtyBits()
m_dirtyBitsVolume.textureFormatDirty = false;
}
+QImage QCustom3DVolumePrivate::renderSlice(Qt::Axis axis, int index)
+{
+ if (index < 0)
+ return QImage();
+
+ int x;
+ int y;
+ if (axis == Qt::XAxis) {
+ if (index >= m_textureWidth)
+ return QImage();
+ x = m_textureDepth;
+ y = m_textureHeight;
+ } else if (axis == Qt::YAxis) {
+ if (index >= m_textureHeight)
+ return QImage();
+ x = m_textureWidth;
+ y = m_textureDepth;
+ } else {
+ if (index >= m_textureDepth)
+ return QImage();
+ x = m_textureWidth;
+ y = m_textureHeight;
+ }
+
+ int padding = 0;
+ int pixelWidth = 4;
+ int dataWidth = qptr()->textureDataWidth();
+ if (m_textureFormat == QImage::Format_Indexed8) {
+ padding = x % 4;
+ pixelWidth = 1;
+ }
+ QVector<uchar> data((x + padding) * y * pixelWidth);
+ int frameSize = qptr()->textureDataWidth() * m_textureHeight;
+
+ int dataIndex = 0;
+ if (axis == Qt::XAxis) {
+ for (int i = 0; i < y; i++) {
+ const uchar *p = m_textureData->constData()
+ + (index * pixelWidth) + (dataWidth * i);
+ for (int j = 0; j < x; j++) {
+ for (int k = 0; k < pixelWidth; k++)
+ data[dataIndex++] = *(p + k);
+ p += frameSize;
+ }
+ }
+ } else if (axis == Qt::YAxis) {
+ for (int i = 0; i < y; i++) {
+ const uchar *p = m_textureData->constData() + (index * dataWidth)
+ + (frameSize * i);
+ for (int j = 0; j < (x * pixelWidth); j++) {
+ data[dataIndex++] = *p;
+ p++;
+ }
+ }
+ } else {
+ for (int i = 0; i < y; i++) {
+ const uchar *p = m_textureData->constData() + (index * frameSize) + (dataWidth * i);
+ for (int j = 0; j < (x * pixelWidth); j++) {
+ data[dataIndex++] = *p;
+ p++;
+ }
+ }
+ }
+
+ if (m_textureFormat != QImage::Format_Indexed8 && m_alphaMultiplier != 1.0f) {
+ for (int i = pixelWidth - 1; i < data.size(); i += pixelWidth)
+ data[i] = static_cast<uchar>(multipliedAlphaValue(data.at(i)));
+ }
+
+ QImage image(data.constData(), x, y, x * pixelWidth, m_textureFormat);
+ image.bits(); // Call bits() to detach the new image from local data
+ if (m_textureFormat == QImage::Format_Indexed8) {
+ QVector<QRgb> colorTable = m_colorTable;
+ if (m_alphaMultiplier != 1.0f) {
+ for (int i = 0; i < colorTable.size(); i++) {
+ QRgb curCol = colorTable.at(i);
+ int alpha = multipliedAlphaValue(qAlpha(curCol));
+ if (alpha != qAlpha(curCol))
+ colorTable[i] = qRgba(qRed(curCol), qGreen(curCol), qBlue(curCol), alpha);
+ }
+ }
+ image.setColorTable(colorTable);
+ }
+
+ return image;
+}
+
+int QCustom3DVolumePrivate::multipliedAlphaValue(int alpha)
+{
+ int modifiedAlpha = alpha;
+ if (!m_preserveOpacity || alpha != 255) {
+ modifiedAlpha = int(m_alphaMultiplier * float(alpha));
+ modifiedAlpha = qMin(modifiedAlpha, 255);
+ }
+ return modifiedAlpha;
+}
+
QCustom3DVolume *QCustom3DVolumePrivate::qptr()
{
return static_cast<QCustom3DVolume *>(q_ptr);
diff --git a/src/datavisualization/data/qcustom3dvolume.h b/src/datavisualization/data/qcustom3dvolume.h
index 00733d17..2f95fa5d 100644
--- a/src/datavisualization/data/qcustom3dvolume.h
+++ b/src/datavisualization/data/qcustom3dvolume.h
@@ -40,7 +40,8 @@ class QT_DATAVISUALIZATION_EXPORT QCustom3DVolume : public QCustom3DItem
Q_PROPERTY(QVector<QRgb> colorTable READ colorTable WRITE setColorTable NOTIFY colorTableChanged)
Q_PROPERTY(QVector<uchar> *textureData READ textureData WRITE setTextureData NOTIFY textureDataChanged)
Q_PROPERTY(QImage::Format textureFormat READ textureFormat WRITE setTextureFormat NOTIFY textureFormatChanged)
-
+ Q_PROPERTY(float alphaMultiplier READ alphaMultiplier WRITE setAlphaMultiplier NOTIFY alphaMultiplierChanged)
+ Q_PROPERTY(bool preserveOpacity READ preserveOpacity WRITE setPreserveOpacity NOTIFY preserveOpacityChanged)
public:
explicit QCustom3DVolume(QObject *parent = 0);
@@ -80,6 +81,11 @@ public:
void setTextureFormat(QImage::Format format);
QImage::Format textureFormat() const;
+ void setAlphaMultiplier(float mult);
+ float alphaMultiplier() const;
+ void setPreserveOpacity(bool enable);
+ bool preserveOpacity() const;
+
QImage renderSlice(Qt::Axis axis, int index);
signals:
@@ -92,6 +98,8 @@ signals:
void colorTableChanged();
void textureDataChanged(QVector<uchar> *data);
void textureFormatChanged(QImage::Format format);
+ void alphaMultiplierChanged(float mult);
+ void preserveOpacityChanged(bool enabled);
protected:
QCustom3DVolumePrivate *dptr();
diff --git a/src/datavisualization/data/qcustom3dvolume_p.h b/src/datavisualization/data/qcustom3dvolume_p.h
index 69dd1eb2..b83e27fb 100644
--- a/src/datavisualization/data/qcustom3dvolume_p.h
+++ b/src/datavisualization/data/qcustom3dvolume_p.h
@@ -40,13 +40,15 @@ struct QCustomVolumeDirtyBitField {
bool colorTableDirty : 1;
bool textureDataDirty : 1;
bool textureFormatDirty : 1;
+ bool alphaDirty : 1;
QCustomVolumeDirtyBitField()
: textureDimensionsDirty(false),
sliceIndicesDirty(false),
colorTableDirty(false),
textureDataDirty(false),
- textureFormatDirty(false)
+ textureFormatDirty(false),
+ alphaDirty(false)
{
}
};
@@ -64,6 +66,7 @@ public:
virtual ~QCustom3DVolumePrivate();
void resetDirtyBits();
+ QImage renderSlice(Qt::Axis axis, int index);
QCustom3DVolume *qptr();
@@ -79,9 +82,14 @@ public:
QVector<QRgb> m_colorTable;
QVector<uchar> *m_textureData;
+ float m_alphaMultiplier;
+ bool m_preserveOpacity;
+
QCustomVolumeDirtyBitField m_dirtyBitsVolume;
private:
+ int multipliedAlphaValue(int alpha);
+
friend class QCustom3DVolume;
};