[Qt-interest] Map to view from inside QGraphicsItem::paint()

Josiah Bryan jbryan at productiveconcepts.com
Mon Oct 19 14:59:36 CEST 2009


Josiah Bryan wrote:
> Josiah Bryan wrote:
>> Hi All -
>>
>> Is there any way for me to be able to map my bounding rect inside a 
>> QGraphicsItem::paint() call to the actual pixel size on the screen?
>>
>> This is for the purpose of scaling large pixmaps to the "right" size. If 
>> my item is scaled up, and I only render the pixmap at the size of my 
>> item, the final pixmap will implicitly be scaled up by the view/scene 
>> scaling. I want to cache the scaled pixmap size that is the actual 
>> screen size and render a good quality pixmap at the same time.
>>   
> Maybe I should explain more:
> 
> I've got a large jpeg ( > 3MB on disk) that I'm rendering.
> 
> Since I'm rendering it at a scaled down size of its original (around 
> 1024x768 instead of the 3000px or whatever the orig width is), I don't 
> want the QPainter to have to scale the 3000px -> 1024px every time it 
> paints. So I want to draw the scaled version to a pixmap and cache the 
> pixmap. Great. Works fine.
> 
> Problem is that if I do that cached pixmap version, the final output 
> looks "block" / pixelated in the final QGraphicsView (since the view may 
> be scaled to fit the target output screen, in this case a 1400x900 at 
> the moment), so the final scene is scaled up a bit. Which results in 
> blocky pixels when using the cached pixmap version.
> 
> But if I just pass the original 3000px pixmap to the painter and let it 
> do the scaling on the fly, the resulting image is much clearer. (I'm 
> using the painter->drawPixmap(QRect,QPixmap) form of the function to do 
> the scaling).
> 
> And the sizes are the same - e.g. the size of the QRect that I use when 
> I give it the 3000px image is the same rect size that I use to draw the 
> cached pixmap - so the only explanation I can see for the differing 
> visual outputs is the view transformations.
> 
> Does anyone have any ideas how to get around that and render "good 
> looking" pixmaps while retaining the speed advantage of caching the 
> scaled pixmaps?

Don't everyone talk at once :-)

In the absence of any responses, I experimented till I was cross-eyed 
and blurry from staring at code. Finally, I came up with a workable 
solution:

     QRect viewRect = painter->combinedTransform().mapRect(myRect);

Basically, inside my QGraphicsItem::paint(), I ask the painter what size 
myRect will be when its actually painted.

Then I scale the pixmap that I'm drawing (the really large one, 
remember?) not to myRect.size(), but instead to viewRect.size().

Now, the trick is that when I finally do call painter->drawPixmap(), I 
still give it myRect, not viewRect. That way, drawPixmap() will do the 
same transform on myRect, realize it needs the size I found in viewRect, 
and check the pixmap I gave it - and realize that no scaling is needed! 
Voila - 1:1 scaled, cached pixmaps.

So, it kinda looks like this:


     QRect myRect = ...;
     QRect viewRect = painter->combinedTransform().mapRect(myRect);

     // Not shown here: scale the original pixmap to viewRect.size() and 
cache

     painter->drawPixmap(myRect, pixmap);


I use QPixmapCache with a key tied to the viewRect.size() to cache the 
results of the scaled pixmap.

Hope that helps someone down the line.

Cheers!
-josiah





More information about the Qt-interest-old mailing list