[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