Bug 120223 - Gradient fill is slow
Summary: Gradient fill is slow
Status: RESOLVED FIXED
Alias: None
Product: krita
Classification: Applications
Component: General (show other bugs)
Version: unspecified
Platform: unspecified Linux
: NOR wishlist
Target Milestone: ---
Assignee: Halla Rempt
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2006-01-16 05:14 UTC by Robert Knight
Modified: 2006-02-12 22:28 UTC (History)
0 users

See Also:
Latest Commit:
Version Fixed In:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Robert Knight 2006-01-16 05:14:24 UTC
Version:           1.4.88 (using KDE 3.5.0, Kubuntu Package 4:3.5.0-0ubuntu0breezy1 breezy)
Compiler:          Target: i486-linux-gnu
OS:                Linux (i686) release 2.6.12-10-386

The gradient fill tool seems quite slow at the moment.  On my AMD 2400+ PC it takes around 10 seconds to gradient fill a 500x500 pixel area (RGB 8bits / channel image , simple three-color stock gradient)  

I should note that I have Krita compiled in debug mode.
Comment 1 Halla Rempt 2006-01-16 10:39:42 UTC
Not a bug, but a wish.
Comment 2 Halla Rempt 2006-02-12 22:28:44 UTC
SVN commit 508851 by rempt:

Speedup gradients a lot. This does not introduce colorspace problems because gradients
have always been defined in QColors. For 2.0, we might want to try our hand at L*a*b 
gradients :-).
BUG:120223



 M  +1 -0      core/kis_gradient.h  
 M  +26 -29    core/kis_gradient_painter.cc  
 M  +0 -1      ui/kis_paintop_box.cc  


--- trunk/koffice/krita/core/kis_gradient.h #508850:508851
@@ -243,6 +243,7 @@
     virtual QImage generatePreview(int width, int height) const;
 
     void colorAt(double t, QColor *color, Q_UINT8 *opacity) const;
+    
     KisGradientSegment *segmentAt(double t) const;
 
 protected:
--- trunk/koffice/krita/core/kis_gradient_painter.cc #508850:508851
@@ -52,6 +52,8 @@
 #include "kis_vec.h"
 #include "kis_selection.h"
 #include "kis_gradient_painter.h"
+#include "kis_meta_registry.h"
+#include "kis_colorspace_factory_registry.h"
 
 namespace {
 
@@ -479,7 +481,6 @@
 {
 }
 
-// XXX: Use KisColor here instead of QColor
 bool KisGradientPainter::paintGradient(const KisPoint& gradientVectorStart,
                        const KisPoint& gradientVectorEnd,
                        enumGradientShape shape,
@@ -534,12 +535,8 @@
     }
     Q_ASSERT(repeatStrategy != 0);
 
-    KisPaintDeviceSP layer = new KisPaintDevice( m_device -> colorSpace(), "gradient layer");
-    Q_CHECK_PTR(layer);
-
-    KisPainter painter(layer);
-
-    //If the device has a selection only iterate of that selection
+    
+    //If the device has a selection only iterate over that selection
     QRect r;
     if( m_device -> hasSelection() ) {
         r = m_device -> selection() -> selectedExactRect();
@@ -554,6 +551,9 @@
     Q_INT32 endx = startx + width - 1;
     Q_INT32 endy = starty + height - 1;
 
+    QImage layer (width, height, 32);
+    layer.setAlphaBuffer(true);
+    
     int pixelsProcessed = 0;
     int lastProgressPercent = 0;
 
@@ -566,7 +566,6 @@
     }
 
     for (int y = starty; y <= endy; y++) {
-        KisHLineIterator iter = layer -> createHLineIterator(startx, y, width, true);
         for (int x = startx; x <= endx; x++) {
 
             double t = shapeStrategy -> valueAt( x, y);
@@ -580,8 +579,10 @@
             Q_UINT8 opacity;
 
             m_gradient -> colorAt(t, &color, &opacity);
-            layer -> colorSpace() -> fromQColor( color, opacity, iter.rawData());
-
+            
+            layer.setPixel(x - startx, y - starty,
+                           qRgba(color.red(), color.green(), color.blue(), opacity));
+            
             pixelsProcessed++;
 
             int progressPercent = (pixelsProcessed * 100) / totalPixels;
@@ -594,8 +595,6 @@
                     break;
                 }
             }
-            ++iter;
-
             if (m_cancelRequested) {
                 break;
             }
@@ -605,18 +604,15 @@
     if (!m_cancelRequested && antiAliasThreshold < 1 - DBL_EPSILON) {
 
         emit notifyProgressStage(i18n("Anti-aliasing gradient..."), lastProgressPercent);
-        KisColorSpace * cs = layer->colorSpace();
+        Q_UINT8 * layerPointer = layer.bits();
         for (int y = starty; y <= endy; y++) {
-            KisHLineIterator iter = layer -> createHLineIterator(startx, y, width, true);
             for (int x = startx; x <= endx; x++) {
 
                 double maxDistance = 0;
 
-                QColor thisPixel;
-                Q_UINT8 thisPixelOpacity;
-
-                cs->toQColor(iter.rawData(), &thisPixel, &thisPixelOpacity);
-
+                QColor thisPixel(layerPointer[2], layerPointer[1], layerPointer[0]);
+                Q_UINT8 thisPixelOpacity = layerPointer[3];
+            
                 for (int yOffset = -1; yOffset < 2; yOffset++) {
                     for (int xOffset = -1; xOffset < 2; xOffset++) {
 
@@ -625,11 +621,12 @@
                             int sampleY = y + yOffset;
 
                             if (sampleX >= startx && sampleX <= endx && sampleY >= starty && sampleY <= endy) {
-                                QColor color;
-                                Q_UINT8 opacity;
-
-                                layer -> pixel(sampleX, sampleY, &color, &opacity);
-
+                                uint x = sampleX - startx;
+                                uint y = sampleY - starty;
+                                Q_UINT8 * pixelPos = layer.bits() + (y * width * 4) + (x * 4);
+                                QColor color(*(pixelPos +2), *(pixelPos + 1), *pixelPos);
+                                Q_UINT8 opacity = *(pixelPos + 3);
+                                
                                 double dRed = (color.red() * opacity - thisPixel.red() * thisPixelOpacity) / 65535.0;
                                 double dGreen = (color.green() * opacity - thisPixel.green() * thisPixelOpacity) / 65535.0;
                                 double dBlue = (color.blue() * opacity - thisPixel.blue() * thisPixelOpacity) / 65535.0;
@@ -686,9 +683,7 @@
                     int blue = totalBlue / (numSamples * numSamples);
                     int opacity = totalOpacity / (numSamples * numSamples);
 
-                    QColor color(red, green,  blue);
-
-                    cs-> fromQColor( color, opacity, iter.rawData());
+                    layer.setPixel(x - startx, y - starty, qRgba(red, green, blue, opacity));
                 }
 
                 pixelsProcessed++;
@@ -703,7 +698,7 @@
                         break;
                     }
                 }
-                ++iter;
+                layerPointer += 4;
             }
 
             if (m_cancelRequested) {
@@ -713,7 +708,9 @@
     }
 
     if (!m_cancelRequested) {
-        bltSelection(startx, starty, m_compositeOp, layer.data(), m_opacity, startx, starty, width, height);
+        KisPaintDeviceSP dev = new KisPaintDevice(KisMetaRegistry::instance()->csRegistry()->getRGB8(), "temporary device for gradient");
+        dev->writeBytes(layer.bits(), startx, starty, width, height);
+        bltSelection(startx, starty, m_compositeOp, dev, m_opacity, startx, starty, width, height);
     }
     delete shapeStrategy;
 
--- trunk/koffice/krita/ui/kis_paintop_box.cc #508850:508851
@@ -234,7 +234,6 @@
     }
 
     const int index = m_paintops->findIndex(paintop);
-    Q_ASSERT(index >= 0 && index < (int)settingsArray.count());
     if (index >= 0 && index < (int)settingsArray.count())
         return settingsArray[index];
     else