Forums Archived

The forums are being archived. See this topic for more information.

Changing contrasts on an image/surface

Get help and support with Rubygame

Changing contrasts on an image/surface

Postby cgmjr » Thu Jan 14, 2010 6:58 am

I'm interested in programmaticly (sp?) changing the contrast of an image that I have loaded onto a surface. I'm not sure that contrast is the right term, but that is how I think of of it. For example, let's say I have an image that is a simple rectangle, one side grey, one side black. I'd like to "fade out" the black slowly.

I've fiddled with Surface#set_alpha, but nothing occurs. It is possible I don't get how alpha really works, but I was expecting the image to "dim" when I did image.set_alpha(123). Nada.

Is the issue that I'm dealing with a image rather than just a plain ol' Surface?

Thanks in advance. I'm having fun with Rubygame.
User avatar
cgmjr
 
Posts: 39
Joined: Mon Jan 11, 2010 6:41 am

Re: Changing contrasts on an image/surface

Postby cgmjr » Sat Jan 16, 2010 4:37 am

Through a bit more experimenting I got this to work, but it feels clumsy. Is it true that one must call Rubygame::Screen.new() in order to change the alpha of the surface thereon?

Here's my play code. Forgive the use of the global, I'm just playing around, starting from the samples/image_viewer.rb:

Code: Select all
  # Load the image
  $image = Surface.load( file )

  # Open a new Rubygame window to fit the image.
  $screen = Screen.open( $image.size )
  $screen.title = File.basename(file)

  # Blit ("paste") the image onto the screen.
  $image.blit( $screen, [0,0] )

MAXALPHA = 255 # Maximum alpha value
ALPHASTEP = 10 # How much to dim/brighten the image
MINALPHA = 0   # Mimimum alpha value

def make_dim
  $screen=Screen.new($image.size)
  $image.alpha < ALPHASTEP ? $image.alpha=MINALPHA : $image.alpha -= ALPHASTEP
  $image.blit($screen,[0,0])
  puts "Dim: Image alpha now #{$image.alpha}"
end

def make_bright
  $screen=Screen.new($image.size)
  $image.alpha > MAXALPHA-ALPHASTEP ? $image.alpha=MAXALPHA : $image.alpha += ALPHASTEP
  $image.blit($screen,[0,0])
  puts "Brighten: Image alpha now #{$image.alpha}"
end
User avatar
cgmjr
 
Posts: 39
Joined: Mon Jan 11, 2010 6:41 am

Re: Changing contrasts on an image/surface

Postby jacius » Sat Jan 16, 2010 7:52 am

Alpha is a bit awkward in SDL and in Rubygame, unfortunately. :|

There are two types of alpha: per-surface alpha, and per-pixel alpha. You can only have one or the other, not both. If your surface has per-pixel alpha, setting per-surface alpha will have no effect.

Per-surface means the surface as a whole has an alpha value, like the opacity slider in a program like Photoshop. This is what you control with the #alpha and #alpha= methods.

Per-pixel means each pixel has its own alpha value, which can be different from other pixels. This adds another color channel to each pixel, so it will be [R,G,B,A] instead of [R,G,B]. You can use the #set_at method to change the color values (including alpha). Unfortunately, there's not currently any fast or easy way to adjust the alpha values of many pixels at once.

Due to a bug in Rubygame, there are only two ways to get a surface that has per-pixel alpha: by loading an image with an alpha channel (like a PNG with transparency), or by using the #to_display_alpha method. Unfortunately, the bug has been in Rubygame since the very beginning, and fixing it might cause some existing applications to break. It'll be fixed in 3.0, though. Whenever that is. :roll:

(There is also a third thing, called a color key, which affects transparency when blitting, but I'll spare you the details about that right now.)

Anyway, getting to your issue:

  • If you want per-pixel alpha, and you are not loading an image with an alpha channel, then yes, you must call Rubygame::Screen.new, and then surface#to_display_alpha.
  • Does the image you are loading have an alpha channel? (If you don't know, you could upload it and I'll check.) If it does, then using #alpha= will have no effect.
  • Blitting in Rubygame is cumulative. In other words, blitting an image onto another image will never make the second image less opaque. So you can't make it "dimmer" by blitting at 255, then 245, then 235... It will always look fully opaque after the first blit at 255. If you want to make it fade out, you must clear the target surface between each blit, e.g. with "$screen.fill(:black)".
  • You should also clear the target surface between each blit when fading in, if you want a perfect linear fade. Otherwise the accumulation will affect things. For example, blitting at 10 and then 20 will be more opaque than just blitting at 20.
User avatar
jacius
Site Admin
 
Posts: 131
Joined: Fri Feb 06, 2009 11:13 pm

Re: Changing contrasts on an image/surface

Postby cgmjr » Mon Jan 18, 2010 2:38 am

Thank you for the reply, jacius. I follow your reply, but I can't apply it yet; I'll have to experiment with per-pixel alpha.

Perhaps I should just describe what I want, and ask for guidance from you and/or my fellow Rubygamers.

I'd like to fade-in an image slowly, in fullscreen mode. I'd like the screen to be a given background color, such as [192,192,192] rgb. My image will include a shape or equation that is a slightly different color, such as [195,195,195].

Fwiw, My project idea is more of a scientific visualization than a game, but Rubygame appears to have much of what I need.

Finally, I -have- gotten this to work with my existing, clumsy code. But in [FULLSCREEN] mode I get awful flickering. In windowed mode it is fine. I thought it was a framerate thing, but using Clock and following the examples of managing framerate did not help. *shrug*
User avatar
cgmjr
 
Posts: 39
Joined: Mon Jan 11, 2010 6:41 am

Re: Changing contrasts on an image/surface

Postby cgmjr » Thu Feb 04, 2010 5:33 am

Update on my alpha stuff. I have the behavior that I want using images that have no alpha channel, such as a jpg. So that'll work for now.

But may I /bump the other question I had? Namely, using surface alpha and Screen.new in FULLSCREEN mode yields horrible flicker. I've declared [HWSURFACE,DOUBLEBUF,FULLSCREEN] on all of me Screen.new's. No joy.

I do not have a Clock or any Framerate stuff going...

thx.
User avatar
cgmjr
 
Posts: 39
Joined: Mon Jan 11, 2010 6:41 am

Re: Changing contrasts on an image/surface

Postby jacius » Sat Feb 06, 2010 10:57 pm

cgmjr wrote:But may I /bump the other question I had? Namely, using surface alpha and Screen.new in FULLSCREEN mode yields horrible flicker. I've declared [HWSURFACE,DOUBLEBUF,FULLSCREEN] on all of me Screen.new's. No joy.

I do not have a Clock or any Framerate stuff going...

When you have DOUBLEBUF enabled, are you using Screen#flip? Screen#update does not work well with double buffering, which can lead to flickering. (It's perfectly fine to use #flip even if you don't have double buffering enabled, by the way. In that case, it just does the same thing as #update with no arguments.)

Also, it's possible that even though you requested HWSURFACE and DOUBLEBUF, SDL wasn't able to do it for some reason; this is actually fairly common. You can check by comparing screen's flags with bitwise AND operator ("&"; not to be confused with the logical AND operator, "&&"):

Code: Select all
require 'rubygame'
include Rubygame
screen = Screen.open([640,480], 0, [HWSURFACE,DOUBLEBUF,FULLSCREEN])
puts "HWSURFACE enabled" if (screen.flags & HWSURFACE) != 0
puts "DOUBLEBUF enabled" if (screen.flags & DOUBLEBUF) != 0
User avatar
jacius
Site Admin
 
Posts: 131
Joined: Fri Feb 06, 2009 11:13 pm


Return to Help & Support

Who is online

Users browsing this forum: No registered users and 1 guest

cron