On Wed, Oct 12, 2011 at 10:36 PM, Oliver Eichler <[email protected]>wrote:
> Am 12.10.2011 12:35, schrieb Dmitry Guryanov:
>
> On Wed, Oct 12, 2011 at 1:16 PM, Oliver Eichler<[email protected]>**
>> wrote:
>>
>> Hi Dmitry,
>>>
>>> I know, but QPixmap is not threadsafe. As there are already some thread
>>> functions that use the draw handlers, too, and future development might
>>> tend
>>> to do map rendering in a thread, the current implementation should avoid
>>> the
>>> usage of QPixmap in the objects that inherit IMap.
>>>
>>>
>>> I know 3 another ways to increase rendering speed:
>>
>> 1. Don't draw to the QImage in COsmTilesHash::getImage. Create some class,
>> which store qimage and qpoint (where qimage must be draw) and put object
>> of
>> this class to list, then in CMapOSM::draw iterate through this list and
>> draw
>> each tile to screen directly - I've checked this method, and it reduces
>> render time about 2 times.
>>
>
> If I recall right Marc's idea (the guy who implemented all OSM/TMS support)
> was to update the screen with each tile received, to give feedback to the
> user. If I understand your idea correctly the screen would just update after
> all tiles are loaded.
>
>
No, COsmTilesHash::slotRequestFinished will add object for new tile to the
list and do emit newImageReady, but this method will break idea with
internal buffer, and it will not help a lot to make map scrolling smooth :(
>
>
>> 2. Try to guess pixel format of screen and create QImages with that pixel
>> format - this change significantly improves performance.
>>
>
> As long as this does not affect the IMap::buffer QImage it's a good idea.
> This buffer, common to all map objects, has to be able to handle the alpha
> channel, as Garmin or raster maps use transparency. Even in CMapOSM
> transparency is need when drawing a vector map as overlay.
>
If alfa channel is needed, this method will not wok :( QImages with such
pixel format are being drawn to screen slowly.
> On my Linux boxes and my win7 netbook the OSM drawing performance has never
> been a problem. But if it's such a performance ditch on your system I think
> your idea is fair enough.
>
>
I've compared qlandkarte with web applications, like
http://www.openstreetmap.org/ and maps.google.com - web apps works
excellent, i don't see any delays at all, but in qlandkarte update rate is
small :( Please, try to run qlandkarte with patch in attachment and check
output, on my system - fedora 15, Core(TM)2 Duo CPU E6750, nvidia adapter,
screen size 1600x1200 and with maximized window it shows about 11 FPS :(
With pixmaps it shows 40-400 fps (maybe some problem with qt events and
synchronization exists, paintEvent works 2.5 ms, so it can be always
400fps).
>
>> 3. Create separate hash for storing tiles in QPixmaps and convert QImages
>> to
>> QPixmaps in GUI thread.
>>
>
> Well the method CMapOSM::draw(QPainter& p) can be called by the GUI thread
> or from any other point. If that does make sense in the case of CMapOSM can
> be discussed, as the method will just trigger tile download and draw the
> current IMap::buffer. CMapOSM will update itself automatically until all
> visible tiles are loaded. This is no real concept for a background thread,
> that expects a complete map after the call.
>
> Thus it would be an option to bypass the IMap::buffer use QPixmap
> completely for CMapOSM and COsmTilesHash. But CMapOSM::draw(QPainter& p)
> should make sure just be called in the main thread. Not sure if that can be
> checked by the Qt API to make it portable.
>
> It's possible but my intuition tells me that I will regret one day ;)
>
>
Maybe create one separate method, which will be called only from GUI thread
and second - method, which must be thread safe. In simplest case first will
just call second, but when some optimization is possible - we can add fast
and thread-unsafe code for drawing to screen ?
> Oliver
>
>
>
>
>>> -------- Original-Nachricht --------
>>>
>>>> Datum: Wed, 12 Oct 2011 11:11:27 +0400
>>>> Von: Dmitry Guryanov<dmitry.guryanov@**gmail.com<[email protected]>
>>>> >
>>>> An:
>>>> qlandkartegt-users@lists.**sourceforge.net<[email protected]>
>>>> CC: [email protected]
>>>> Betreff: [Qlandkartegt-users] [PATCH] use QPixmap instead of QImage for
>>>>
>>> drawing OSM map
>>>
>>> QImage is optimized for IO, as states QT documentation,
>>>> and operation like drawing one QImage to another or
>>>> drawing QImage to screen are very slow, especially when
>>>> pixel format of QImage not same as screen (on my system
>>>> pixel format of screen is rgb32, but qlandkarte use
>>>> QImage::Format_ARGB32_**Premultiplied).
>>>>
>>>> Using QPixmap speeds up paintEvent handler, before this
>>>> patch time of CCanvas::paintEvent was ~85ms, after - ~2.5ms.
>>>> Update rate is still not high, about 40FPS, because
>>>> of qt events, but map moves more smoothly.
>>>> ---
>>>> src/CMapOSM.cpp | 8 ++++----
>>>> src/CMapOSM.h | 5 +++--
>>>> src/COsmTilesHash.cpp | 16 ++++++++++------
>>>> src/COsmTilesHash.h | 8 ++++----
>>>> 4 files changed, 21 insertions(+), 16 deletions(-)
>>>>
>>>> diff --git a/src/CMapOSM.cpp b/src/CMapOSM.cpp
>>>> index 5c25462..c9cb2d7 100644
>>>> --- a/src/CMapOSM.cpp
>>>> +++ b/src/CMapOSM.cpp
>>>> @@ -216,7 +216,7 @@ void CMapOSM::setNewTileUrl(int cbIndex)
>>>> }
>>>>
>>>> osmTiles = new COsmTilesHash(tileList.at(**index).path);
>>>> -
>>>>
>>>> connect(osmTiles,SIGNAL(**newImageReady(QImage,bool)),**
>>> this,SLOT(newImageReady(**QImage,bool)));
>>>
>>>> +
>>>>
>>>> connect(osmTiles,SIGNAL(**newImageReady(QPixmap,bool)),**
>>> this,SLOT(newImageReady(**QPixmap,bool)));
>>>
>>>>
>>>> needsRedraw = true;
>>>> emit sigChanged();
>>>> @@ -370,7 +370,7 @@ void CMapOSM::draw(QPainter& p)
>>>> draw();
>>>> }
>>>>
>>>> - p.drawImage(0,0,buffer);
>>>> + p.drawPixmap(0, 0, image);
>>>>
>>>> // render overlay
>>>> if(!ovlMap.isNull()&& lastTileLoaded&& !doFastDraw)
>>>>
>>>> @@ -437,9 +437,9 @@ void CMapOSM::draw()
>>>> }
>>>>
>>>>
>>>> -void CMapOSM::newImageReady(QImage image, bool done)
>>>> +void CMapOSM::newImageReady(QPixmap image, bool done)
>>>> {
>>>> - buffer = image;
>>>> + this->image = image;
>>>> lastTileLoaded = done;
>>>> needsRedraw = false;
>>>> emit sigChanged();
>>>> diff --git a/src/CMapOSM.h b/src/CMapOSM.h
>>>> index 6b7e2f8..2a44081 100644
>>>> --- a/src/CMapOSM.h
>>>> +++ b/src/CMapOSM.h
>>>> @@ -21,6 +21,7 @@
>>>> #define CMAPOSM_H
>>>>
>>>> #include<IMap.h>
>>>> +#include<QPixmap>
>>>> #include "CMapOSMType.h"
>>>>
>>>> class COsmTilesHash;
>>>> @@ -49,14 +50,14 @@ class CMapOSM : public IMap
>>>> bool rebuildServerList();
>>>>
>>>> public slots:
>>>> - void newImageReady(QImage image, bool lastTileLoaded);
>>>> + void newImageReady(QPixmap image, bool lastTileLoaded);
>>>> void setNewTileUrl(int cbIndex = -1);
>>>> private:
>>>> QComboBox *cb;
>>>> QWidget *parent;
>>>> int currentTileListIndex;
>>>> QList<CMapOSMType> tileList;
>>>> - QImage image;
>>>> + QPixmap image;
>>>> bool lastTileLoaded;
>>>> void draw();
>>>> COsmTilesHash *osmTiles;
>>>> diff --git a/src/COsmTilesHash.cpp b/src/COsmTilesHash.cpp
>>>> index 3455cc0..7471f36 100644
>>>> --- a/src/COsmTilesHash.cpp
>>>> +++ b/src/COsmTilesHash.cpp
>>>> @@ -183,7 +183,7 @@ void COsmTilesHash::**startNewDrawing( double lon,
>>>> double lat, int osm_zoom, const
>>>>
>>>> //qDebug()<< xCount<< yCount<< window;
>>>>
>>>> - image = QImage(window.size(),QImage::**
>>>> Format_ARGB32_Premultiplied);
>>>> + image = QPixmap(window.size());
>>>> image.fill(Qt::white);
>>>> for(int x=0; x<xCount; x++)
>>>> {
>>>> @@ -212,7 +212,7 @@ void COsmTilesHash::getImage(int osm_zoom, int
>>>> osm_x,
>>>> int osm_y, QPoint point)
>>>> if (tiles.contains(osmUrlPart))
>>>> {
>>>> QPainter p(&image);
>>>> - p.drawImage(point,tiles.value(**osmUrlPart));
>>>> + p.drawPixmap(point,tiles.**value(osmUrlPart));
>>>> #ifdef COSMTILESHASHDEBUG
>>>> p.drawRect(QRect(point,QSize(**255,255)));
>>>> p.drawText(point + QPoint(10,10), "cached " + osmUrlPart);
>>>> @@ -229,9 +229,11 @@ void COsmTilesHash::getImage(int osm_zoom, int
>>>>
>>> osm_x,
>>>
>>>> int osm_y, QPoint point)
>>>>
>>>> if(img1.format() != QImage::Format_Invalid)
>>>> {
>>>> + QPixmap pix1(img1.size());
>>>> + pix1.convertFromImage(img1);
>>>> QPainter p(&image);
>>>> - p.drawImage(point,img1);
>>>> - tiles.insert(osmUrlPart,img1);
>>>> + p.drawPixmap(point,pix1);
>>>> + tiles.insert(osmUrlPart,pix1);
>>>> int days =
>>>>
>>>> QFileInfo(osmFilePath).**lastModified().daysTo(**
>>> QDateTime::currentDateTime());
>>>
>>>> if ( days< 8)
>>>> {
>>>> @@ -309,10 +311,12 @@ void COsmTilesHash::**slotRequestFinished(int id,
>>>>
>>> bool
>>>
>>>> error)
>>>> img1.save (&f);
>>>> }
>>>>
>>>> - tiles.insert(osmUrlPart,img1);
>>>> + QPixmap pix1(img1.size());
>>>> + pix1.convertFromImage(img1);
>>>> + tiles.insert(osmUrlPart,pix1);
>>>> // if (osmUrlPart.startsWith(**QString("/%1/").arg(osm_zoom))**) {
>>>> QPainter p(&image);
>>>> - p.drawImage(startPointHash.**value(id),img1);
>>>> + p.drawPixmap(startPointHash.**value(id),pix1);
>>>> #ifdef COSMTILESHASHDEBUG
>>>> p.drawRect(QRect(**startPointHash.value(id),**QSize(255,255)));
>>>> p.drawText(startPointHash.**value(id) + QPoint(10,10),
>>>> QString::number(id) + osmUrlPartHash.value(id));
>>>> diff --git a/src/COsmTilesHash.h b/src/COsmTilesHash.h
>>>> index f5f6e8f..5ee7d68 100644
>>>> --- a/src/COsmTilesHash.h
>>>> +++ b/src/COsmTilesHash.h
>>>> @@ -20,7 +20,7 @@
>>>> #include<QString>
>>>> #include<QRect>
>>>> #include<QPainter>
>>>> -#include<QImage>
>>>> +#include<QPixmap>
>>>> #include<QHash>
>>>>
>>>> class QHttp;
>>>> @@ -34,7 +34,7 @@ class COsmTilesHash: public QObject
>>>> void startNewDrawing( double lon, double lat, int osm_zoom,
>>>>
>>> const
>>>
>>>> QRect& window);
>>>> static const QString&getCacheFolder(void) { return cacheFolder;
>>>>
>>>> };
>>>> signals:
>>>> - void newImageReady(QImage image, bool lastTileLoaded);
>>>> + void newImageReady(QPixmap image, bool lastTileLoaded);
>>>> private:
>>>> QString tileServer;
>>>> QString tileUrlPart;
>>>> @@ -48,12 +48,12 @@ class COsmTilesHash: public QObject
>>>> double tile2long(int x, int zoom);
>>>> double tile2lat(int y, int zoom);
>>>> void getImage(int osm_zoom, int osm_x, int osm_y, QPoint
>>>> startPoint);
>>>> - QImage image;
>>>> + QPixmap image;
>>>> QHttp *tilesConnection;
>>>> // CMapOSM *cmapOSM;
>>>> QString osmTileBaseUrl;
>>>> bool requestInProgress;
>>>> - QHash<QString,QImage> tiles;
>>>> + QHash<QString,QPixmap> tiles;
>>>> int getid;
>>>> static QString cacheFolder;
>>>> private slots:
>>>> --
>>>> 1.7.6.4
>>>>
>>>>
>>>>
>>>> ------------------------------**------------------------------**
>>> ------------------
>>>
>>>> All the data continuously generated in your IT infrastructure contains a
>>>> definitive record of customers, application performance, security
>>>> threats, fraudulent activity and more. Splunk takes this data and makes
>>>> sense of it. Business sense. IT sense. Common sense.
>>>> http://p.sf.net/sfu/splunk-**d2d-oct<http://p.sf.net/sfu/splunk-d2d-oct>
>>>> ______________________________**_________________
>>>> Qlandkartegt-users mailing list
>>>> Qlandkartegt-users@lists.**sourceforge.net<[email protected]>
>>>> https://lists.sourceforge.net/**lists/listinfo/qlandkartegt-**users<https://lists.sourceforge.net/lists/listinfo/qlandkartegt-users>
>>>>
>>>
>>>
>>
>
------------------------------------------------------------------------------
All the data continuously generated in your IT infrastructure contains a
definitive record of customers, application performance, security
threats, fraudulent activity and more. Splunk takes this data and makes
sense of it. Business sense. IT sense. Common sense.
http://p.sf.net/sfu/splunk-d2d-oct
_______________________________________________
Qlandkartegt-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/qlandkartegt-users