Page 1 of 1

Icky screenshots in 0.8

Posted: Mon Nov 28, 2011 5:32 am
by luminosity
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 5152 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 5152 times
Is there some problem with alpha in screenshots? Some magical incantation I've forgotten?

Thanks!

Re: Icky screenshots in 0.8

Posted: Mon Nov 28, 2011 1:02 pm
by Boolsheet
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 5131 times

Re: Icky screenshots in 0.8

Posted: Wed Nov 30, 2011 5:22 am
by luminosity
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.

Re: Icky screenshots in 0.8

Posted: Wed Nov 30, 2011 7:00 am
by Boolsheet
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 189 times

Re: Icky screenshots in 0.8

Posted: Wed Nov 30, 2011 8:31 am
by miko
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)

Re: Icky screenshots in 0.8

Posted: Wed Nov 30, 2011 4:08 pm
by Boolsheet
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.

Re: Icky screenshots in 0.8

Posted: Thu Dec 01, 2011 6:21 am
by luminosity
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.

Re: Icky screenshots in 0.8

Posted: Thu Dec 01, 2011 5:35 pm
by Boolsheet
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.

Re: Icky screenshots in 0.8

Posted: Thu Dec 01, 2011 6:38 pm
by TechnoCat
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.

Re: Icky screenshots in 0.8

Posted: Fri Dec 02, 2011 4:26 am
by luminosity
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!