[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