[Kst] branches/work/kst/portto4/kst/src
Barth Netterfield
netterfield at astro.utoronto.ca
Mon Aug 30 23:56:45 CEST 2010
SVN commit 1170152 by netterfield:
Some camping fun: lets optimize Image drawing!
Reduce Image draw times from 460ms to 35ms. Its now totally dominated by blitting.
Also fix a couple un-initialzed variables complements of Valgrind.
M +1 -1 datasources/fitsimage/fitsimage.cpp
M +10 -3 libkst/matrix.cpp
M +1 -0 libkst/matrix.h
M +1 -1 libkstapp/applicationsettings.cpp
M +1 -0 libkstapp/plotitem.cpp
M +56 -35 libkstmath/image.cpp
M +1 -1 libkstmath/image.h
M +23 -38 libkstmath/palette.cpp
M +47 -10 libkstmath/palette.h
--- branches/work/kst/portto4/kst/src/datasources/fitsimage/fitsimage.cpp #1170151:1170152
@@ -273,7 +273,7 @@
FitsImageSource::~FitsImageSource() {
- int status;
+ int status = 0;
if (_fptr) {
fits_close_file( _fptr, &status );
_fptr = 0L;
--- branches/work/kst/portto4/kst/src/libkst/matrix.cpp #1170151:1170152
@@ -83,13 +83,20 @@
double Matrix::value(double x, double y, bool* ok) const {
- int x_index = (int)floor((x - _minX) / (double)_stepX);
- int y_index = (int)floor((y - _minY) / (double)_stepY);
+ int x_index = (int)((x - _minX) / (double)_stepX);
+ int y_index = (int)((y - _minY) / (double)_stepY);
- return valueRaw(x_index, y_index, ok);
+ int index = zIndex(x_index, y_index);
+ if ((index < 0) || !finite(_z[index]) || KST_ISNAN(_z[index])) {
+ (*ok) = false;
+ return 0.0;
}
+ (*ok) = true;
+ return _z[index];
+}
+
double Matrix::valueRaw(int x, int y, bool* ok) const {
int index = zIndex(x,y);
if ((index < 0) || !finite(_z[index]) || KST_ISNAN(_z[index])) {
--- branches/work/kst/portto4/kst/src/libkst/matrix.h #1170151:1170152
@@ -147,6 +147,7 @@
virtual void internalUpdate();
+ double Z(int i) const {return _z[i];}
protected:
int _NS;
int _NRealS; // number of samples with real values
--- branches/work/kst/portto4/kst/src/libkstapp/applicationsettings.cpp #1170151:1170152
@@ -51,7 +51,7 @@
//FIXME Not sure if this is the best test for hardware acceleration
// but right now opening with QGV with QGLWidget as viewport takes
// several seconds delay when opening application on my system.
- _useOpenGL = _settings->value("general/opengl", QVariant(QGLPixelBuffer::hasOpenGLPbuffers())).toBool();
+ _useOpenGL = _settings->value("general/opengl", false).toBool(); //QVariant(QGLPixelBuffer::hasOpenGLPbuffers())).toBool();
_maxUpdate = _settings->value("general/minimumupdateperiod", QVariant(200)).toInt();
--- branches/work/kst/portto4/kst/src/libkstapp/plotitem.cpp #1170151:1170152
@@ -68,6 +68,7 @@
_calculatedLeftBaseOffset(0.0),
_calculatedRightLabelMargin(0.0),
_calculatedTopLabelMargin(0.0),
+ _calculatedTopLabelHeight(0.0),
_calculatedBottomLabelMargin(0.0),
_calculatedBottomLabelWidth(0.0),
_calculatedLabelMarginWidth(0.0),
--- branches/work/kst/portto4/kst/src/libkstmath/image.cpp #1170151:1170152
@@ -63,7 +63,7 @@
s.writeAttribute("matrix", _inputMatrices[THEMATRIX]->Name());
}
- if (!_pal.paletteData().isEmpty()) {
+ if (_pal.colorCount()>0) {
s.writeAttribute("palettename", _pal.paletteName());
}
@@ -143,32 +143,20 @@
}
}
-
-QColor Image::getMappedColor(MatrixPtr m, double x, double y) {
- bool ok;
-
- double z = m->value(x, y, &ok);
- if (ok) {
+//FIXME: Inline and optimize!
+QColor Image::getMappedColor(double z) {
int index;
if (_zUpper - _zLower != 0) {
- if (z > _zUpper) {
- index = _pal.paletteData().count() - 1;
- } else if (z < _zLower) {
- index = 0;
+ index = (int)(((z - _zLower) * (_pal.colorCount() - 1)) / (_zUpper - _zLower));
} else {
- index = (int)floor(((z - _zLower) * (_pal.paletteData().count() - 1)) / (_zUpper - _zLower));
- }
- } else {
index = 0;
}
- return _pal.paletteData().value(index);
+ return _pal.color(index);
}
- return QColor();
-}
void Image::setPalette(const Palette &pal) {
- _pal = pal;
+ _pal.changePaletteName(pal.paletteName());
}
@@ -214,7 +202,7 @@
_zUpper = upperZ;
_autoThreshold = autoThreshold;
if (_pal.paletteName() != paletteName) {
- _pal = Palette(paletteName);
+ _pal.changePaletteName(paletteName);
}
_hasColorMap = true;
_hasContourMap = false;
@@ -244,7 +232,7 @@
_zUpper = upperZ;
_autoThreshold = autoThreshold;
if (_pal.paletteName() != paletteName) {
- _pal = Palette(paletteName);
+ _pal.changePaletteName(paletteName);
}
_numContourLines = numContours;
_contourWeight = contourWeight;
@@ -437,8 +425,12 @@
void Image::paintObjects(const CurveRenderContext& context) {
QPainter* p = context.painter;
+
+ if (hasColorMap()) {
p->drawImage(_imageLocation, _image);
+ }
+ if (hasContourMap()) {
QColor lineColor = contourColor();
foreach(CoutourLineDetails lineDetails, _lines) {
@@ -446,8 +438,8 @@
p->drawLine(lineDetails._line);
}
}
+}
-
void Image::updatePaintObjects(const CurveRenderContext& context) {
double Lx = context.Lx, Hx = context.Hx, Ly = context.Ly, Hy = context.Hy;
double m_X = context.m_X, m_Y = context.m_Y, b_X = context.b_X, b_Y = context.b_Y;
@@ -532,26 +524,55 @@
int hXlXDiff = d2i(img_Hx_pix - img_Lx_pix);
int hYlYDiff = d2i(img_Hy_pix - img_Ly_pix - 1);
_image = QImage(hXlXDiff, hYlYDiff, QImage::Format_RGB32);
- for (int y = 0; y < _image.height(); ++y) {
+ //_image.fill(0);
+ int ih = _image.height();
+ int iw = _image.width();
+ double m_minX = m->minX();
+ double m_minY = m->minY();
+ double m_numY = m->yNumSteps();
+ double m_stepYr = 1.0/m->yStepSize();
+ double m_stepXr = 1.0/m->xStepSize();
+ int x_index;
+ int y_index;
+ int palCountMinus1 = _pal.colorCount() - 1;
+ double palCountMin1_OverDZ = double(palCountMinus1) / (_zUpper - _zLower);
+
+ for (int y = 0; y < ih; ++y) {
+ bool okY = true;
+
QRgb *scanLine = (QRgb *)_image.scanLine(y);
- for (int x = 0; x < _image.width(); ++x) {
- double new_x, new_y;
+ double new_y;
+ if (yLog) {
+ new_y = pow(yLogBase, (y + 1 + img_Ly_pix - b_Y) / m_Y);
+ } else {
+ new_y = (y + 1 + img_Ly_pix - b_Y) / m_Y;
+ }
+ y_index = (int)((new_y - m_minY)*m_stepYr);
+ if (y_index<0 || y_index>=m_numY) {
+ okY = false;
+ }
+ double A = img_Lx_pix - b_X;
+ double B = 1.0/m_X;
+ for (int x = 0; x < iw; ++x) {
+ bool okX = true;
+ double new_x;
if (xLog) {
new_x = pow(xLogBase, (x + img_Lx_pix - b_X) / m_X);
} else {
- new_x = (x + img_Lx_pix - b_X) / m_X;
+ new_x = (x + A)*B;
}
- if (yLog) {
- new_y = pow(yLogBase, (y + 1 + img_Ly_pix - b_Y) / m_Y);
+ x_index = (int)((new_x - m_minX)*m_stepXr);
+ double z = m->Z(x_index * m_numY + y_index);
+
+ okX = finite(z);
+
+ if (okX && okY) {
+ scanLine[x] = _pal.rgb((int)(((z - _zLower) * palCountMin1_OverDZ)));
} else {
- new_y = (y + 1 + img_Ly_pix - b_Y) / m_Y;
+ scanLine[x] = 0;
}
- thisPixel = image->getMappedColor(m, new_x, new_y);
- if (thisPixel.isValid()) {
- scanLine[x] = thisPixel.rgb();
}
}
- }
_imageLocation = QPoint(d2i(img_Lx_pix), d2i(img_Ly_pix + 1));
}
#ifdef BENCHMARK
@@ -748,12 +769,12 @@
void Image::paintLegendSymbol(QPainter *p, const QRectF& bound) {
- if (hasColorMap() && !_pal.paletteData().isEmpty()) {
+ if (hasColorMap() && (_pal.colorCount()>0)) {
int l = bound.left(), r = bound.right(), t = bound.top(), b = bound.bottom();
// draw the color palette
for (int i = l; i <= r; i++) {
- int index = (int)floor(static_cast<double>(((i - l) * (_pal.paletteData().count() - 1))) / (r - l));
- QColor sliceColor = _pal.paletteData().value(index).rgb();
+ int index = (int)floor(static_cast<double>(((i - l) * (_pal.colorCount() - 1))) / (r - l));
+ QColor sliceColor = _pal.color(index).rgb();
p->setPen(QPen(sliceColor, 1));
p->drawLine(i, t, i, b);
}
--- branches/work/kst/portto4/kst/src/libkstmath/image.h #1170151:1170152
@@ -51,7 +51,7 @@
virtual QString propertyString() const;
virtual bool getNearestZ(double x, double y, double& z);
- virtual QColor getMappedColor(MatrixPtr m, double x, double y);
+ virtual QColor getMappedColor(double z);
virtual void setPalette(const Palette &pal);
virtual void setUpperThreshold(double z);
virtual void setLowerThreshold(double z);
--- branches/work/kst/portto4/kst/src/libkstmath/palette.cpp #1170151:1170152
@@ -30,80 +30,65 @@
"#105010"
};
static const int KstColorsCount = sizeof(KstColors) / sizeof(char*);
-
static const QString KstColorsName = "Kst Colors";
+
+static const int KstGrayscaleCount = 255;
static const QString KstGrayscaleName = "Kst Grayscale";
-
QStringList Palette::getPaletteList() {
QStringList paletteList;
- //TODO Populate a shared list of colors to return here.
paletteList.append(KstGrayscaleName);
paletteList.append(KstColorsName);
+ //TODO: support loading palettes from disk.
+
return paletteList;
}
-Palette::Palette() {
- createPalette();
+Palette::Palette(): _colors(0), _count(0) {
+ changePaletteName(KstColorsName);
}
-Palette::Palette(const QString &paletteName) {
- createPalette(paletteName);
+Palette::Palette(const QString &paletteName): _colors(0), _count(0) {
+ changePaletteName(paletteName);
}
-
Palette::~Palette() {
+ delete[] _colors;
+ delete[] _rgb;
+ _colors = 0;
+ _count = 0;
}
+void Palette::changePaletteName(const QString &paletteName) {
-QString Palette::paletteName() const {
- return _paletteName;
+ if (_count==0) {
+ _colors = new QColor[2048];
+ _rgb = new QRgb[2048];
}
-
-int Palette::colorCount() const {
- return _count;
-}
-
-PaletteData Palette::paletteData() const {
- return _palette;
-}
-
-QColor Palette::color(const int colorId) const {
- return _palette[colorId];
-}
-
-
-void Palette::createPalette(const QString &paletteName) {
- //TODO Get Palette details from a palette name parameter when a shared list exists.
- _palette.clear();
if (paletteName.isEmpty()) {
_paletteName = KstColorsName;
} else {
- //TODO when a proper shared list exists, validate that the palette exists.
_paletteName = paletteName;
}
if (_paletteName == KstColorsName) {
for (int i = 0; i < KstColorsCount; i++) {
- _palette.insert(i, QColor(KstColors[i]));
+ _colors[i] = QColor(KstColors[i]);
+ _rgb[i] = _colors[i].rgb();
}
+ _count = KstColorsCount;
} else {
- for (int i = 0; i < 255; i++) {
- _palette.insert(i, QColor(i, i, i));
+ for (int i = 0; i < KstGrayscaleCount; i++) {
+ _colors[i] = QColor(i, i, i);
+ _rgb[i] = _colors[i].rgb();
}
+ _count = KstGrayscaleCount;
}
- _count = _palette.count();
}
-
-void Palette::addColor(const QColor& color) {
- _palette.insert(_count, QColor(color));
- ++_count;
}
-
-}
// vim: ts=2 sw=2 et
--- branches/work/kst/portto4/kst/src/libkstmath/palette.h #1170151:1170152
@@ -1,13 +1,14 @@
-/***************************************************************************
+/*******************************************************************************
* *
* copyright : (C) 2007 The University of Toronto *
+ * copyright : (C) 2010 C. Barth Netterfield <netterfield at astro.utoronto.ca> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
- ***************************************************************************/
+ *******************************************************************************/
#ifndef _PALETTE_H
#define _PALETTE_H
@@ -20,25 +21,61 @@
typedef QHash<int, QColor> PaletteData;
+const unsigned int maxColorTableSize = 2048;
+
class KSTMATH_EXPORT Palette
{
public:
+ /**
+ * @returns string list of avalible palettes
+ */
static QStringList getPaletteList();
+
Palette();
Palette(const QString &paletteName);
+
virtual ~Palette();
- void addColor(const QColor & color);
+ void changePaletteName(const QString &paletteName);
+ QString paletteName() const {return _paletteName;}
+ int colorCount() const {return _count;}
- QString paletteName() const;
- int colorCount() const;
- QColor color(const int colorId) const;
- PaletteData paletteData() const;
+ /**
+ * Returns the color corresponding to colorId.
+ * It truncates to max or min _color if colorId is out
+ * of bounds, so bounds checking is not necessary in the
+ * calling function.
+ * @returns the QColor
+ */
+ QColor color(const int colorId) const{
+ if (colorId<0) {
+ return _colors[0];
+ } else if (colorId>=_count) {
+ return _colors[_count-1];
+ } else {
+ return _colors[colorId];
+ }
+ }
+ /**
+ * Returns the rgb value for the color corresponding to colorId.
+ * It truncates to max or min _rgb if colorId is out
+ * of bounds, so bounds checking is not necessary in the
+ * calling function.
+ * @returns the QColor.rgb().
+ */
+ QRgb rgb(const int colorId) const{
+ if (colorId<0) {
+ return _rgb[0];
+ } else if (colorId>=_count) {
+ return _rgb[_count-1];
+ } else {
+ return _rgb[colorId];
+ }
+ }
private:
- void createPalette(const QString &paletteName = QString());
-
- PaletteData _palette;
+ QColor *_colors;
+ QRgb *_rgb;
QString _paletteName;
int _count;
};
More information about the Kst
mailing list