Icky screenshots in 0.8

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
luminosity
Prole
Posts: 34
Joined: Fri Sep 24, 2010 5:46 am

Icky screenshots in 0.8

Post by luminosity » Mon Nov 28, 2011 5:32 am

So I upgraded my game to a build on Love 0.8 recently, as some of the new spiffy features are quite useful, and switched my screenshots over to use PNGs (thanks for the non BMP formats!). Unfortunately...
love-screenshot.png
love-screenshot.png (320.41 KiB) Viewed 2428 times
This is what I get saved when I used the love screenshot saving. I messed around with some different blendmodes and nothing seemed to change. My screenshot function is:

Code: Select all

local function screenshot(key)
	if key ~= 'print' then return end
	if not love.filesystem.exists('screenshots') then
		love.filesystem.mkdir('screenshots')
	end
	local screenName = nextScreenshotName()
	local screen = love.graphics.newScreenshot()
	screen:encode(screenName)
end
What I see, and what a windows screenshot shows me is:
what-i-see.png
what-i-see.png (330.9 KiB) Viewed 2428 times
Is there some problem with alpha in screenshots? Some magical incantation I've forgotten?

Thanks!

User avatar
Boolsheet
Inner party member
Posts: 780
Joined: Wed Dec 29, 2010 4:57 am
Location: Switzerland

Re: Icky screenshots in 0.8

Post by Boolsheet » Mon Nov 28, 2011 1:02 pm

There are some transparent parts in the image and you see the background of the forum/image viewer. The transparent parts are there because that's how the "normal" blend mode works in LÖVE. There's the alternative of a "premultiplied" blend mode now which gives you what you probably want.

There was a discussion in the other thread here.

(Edit: Oh, I forgot. Text ist not compatible with premultiplied.)
(Edit2: You could also post-process the ImageData with mapPixel before you save it and eliminate the transparency. It's slow though.)

The image again with a checkerboard background. Note that text and buttons show background at their edges too.
love-screenshot_rgba.jpg
love-screenshot_rgba.jpg (47.38 KiB) Viewed 2407 times
Shallow indentations.

luminosity
Prole
Posts: 34
Joined: Fri Sep 24, 2010 5:46 am

Re: Icky screenshots in 0.8

Post by luminosity » Wed Nov 30, 2011 5:22 am

I don't really understand why it would keep the transparency, though. The game renders it on top of the background colour, why isn't it blended with that in a screenshot, which I'd think should be a literal translation of what you see?

I previously tried every different blend mode setting before taking the screenshot, and nothing altered what was saved to disk.

User avatar
Boolsheet
Inner party member
Posts: 780
Joined: Wed Dec 29, 2010 4:57 am
Location: Switzerland

Re: Icky screenshots in 0.8

Post by Boolsheet » Wed Nov 30, 2011 7:00 am

I said "normal" blend mode in my previous post. I meant to say "alpha" blend mode.
luminosity wrote:why isn't it blended with that in a screenshot
It is. What you see displayed in the LÖVE window is the image blended against black. (Or maybe it just drops the alpha. I don't know OpenGL that well)
The function love.graphics.setBackgroundColor does not change this behaviour if you mean that by 'background color'. What it does is set the all pixels in the screen buffer to the specified value when love.graphics.clear is called (which LÖVE does by default before love.draw). It's similar to drawing a rectangle with the same color over the whole screen, just without the blending. clear sets the values directly.

The "alpha" blend mode is pretty much linear interpolation of the pixels with the source alpha as the weight. If one of the pixels is translucent, there's a good chance the blended pixel is translucent too.

The "premultiplied" blend mode does not lower the alpha like that, but the images require preprocessing. The color values have to be multiplied with their alpha value.

Here's an example. Use 1 and 2 to switch between alpha and premultiplied. In the bottom-right corner is a screenshot of the scene rendered on top of a white background. Notice white showing through with the alpha blend mode.
pm_example.love
(214.99 KiB) Downloaded 93 times
Shallow indentations.

User avatar
miko
Party member
Posts: 410
Joined: Fri Nov 26, 2010 2:25 pm
Location: PL

Re: Icky screenshots in 0.8

Post by miko » Wed Nov 30, 2011 8:31 am

Boolsheet wrote:Here's an example. Use 1 and 2 to switch between alpha and premultiplied. In the bottom-right corner is a screenshot of the scene rendered on top of a white background. Notice white showing through with the alpha blend mode.
Intersting... I can see no difference. Is that because my driver/card? (mesa/intel GM45)
My lovely code lives at GitHub: http://github.com/miko/Love2d-samples

User avatar
Boolsheet
Inner party member
Posts: 780
Joined: Wed Dec 29, 2010 4:57 am
Location: Switzerland

Re: Icky screenshots in 0.8

Post by Boolsheet » Wed Nov 30, 2011 4:08 pm

No, LÖVE does not request the size of the alpha and the default value is different from vendor to vendor.
I'm going to poke a developer about that.
Shallow indentations.

luminosity
Prole
Posts: 34
Joined: Fri Sep 24, 2010 5:46 am

Re: Icky screenshots in 0.8

Post by luminosity » Thu Dec 01, 2011 6:21 am

Hmm.. I think I understand what you're saying, but I still don't get why the love.graphics.newScreenshot function keeps the backgroundColor set unless transparent pixels are drawn over it.

Is this something I should try to fix, or wait for a change in Love?

Also, thanks a lot for your help.

User avatar
Boolsheet
Inner party member
Posts: 780
Joined: Wed Dec 29, 2010 4:57 am
Location: Switzerland

Re: Icky screenshots in 0.8

Post by Boolsheet » Thu Dec 01, 2011 5:35 pm

newScreenshot makes an exact copy of the screen buffer, it does not alter the data.
The color and alpha changes because that's how the blend mode works.
Let's say we have pixel A from the background and pixel B from the new image. The "alpha" blend mode does now the following calculation to get the blended pixel C. (I adjusted the math to 0 - 255 instead of 0 - 1. The exact equation is in the other thread)

Code: Select all

      A       B                   A                    B                   C
R:   58      70         ( 58 - ( 58 * 140)/255)  +  ( 70 * 140)/255       64
G:   64      80   -->   ( 64 - ( 64 * 140)/255)  +  ( 80 * 140)/255   =   72
B:   54      91         ( 54 - ( 54 * 140)/255)  +  ( 91 * 140)/255       74
A:  255     140         (255 - (255 * 140)/255)  +  (140 * 140)/255      191
The resulting pixel C is not opaque. This is where the transparency comes from.
It looks like OpenGL does indeed just drop the alpha for presentation on the screen. You could do the same with mapPixel to get the desired effect, but it's not very fast.

Code: Select all

img = love.graphics.newScreenshot()
img:mapPixel(
    function(x, y, r, g, b, a)
        return r, g, b, 255
    end
)
We could ask the developers for an extended encode function, but too many options get unlövely and clunky.
Shallow indentations.

User avatar
TechnoCat
Inner party member
Posts: 1611
Joined: Thu Jul 30, 2009 12:31 am
Location: Denver, CO
Contact:

Re: Icky screenshots in 0.8

Post by TechnoCat » Thu Dec 01, 2011 6:38 pm

Boolsheet wrote:We could ask the developers for an extended encode function, but too many options get unlövely and clunky.
It seems the display is both displayed and saved correctly. So no need.

luminosity
Prole
Posts: 34
Joined: Fri Sep 24, 2010 5:46 am

Re: Icky screenshots in 0.8

Post by luminosity » Fri Dec 02, 2011 4:26 am

Boolsheet wrote:

Code: Select all

img = love.graphics.newScreenshot()
img:mapPixel(
    function(x, y, r, g, b, a)
        return r, g, b, 255
    end
)
That gave me exactly what I wanted. Thanks so much!

Post Reply

Who is online

Users browsing this forum: No registered users and 43 guests