GLBasic forum

Main forum => Bug Reports => Topic started by: AndyH on 2008-Feb-04

Title: GRABSPRITE on transparent color problem with ZOOMSPRITE/STRETCHSPRITE
Post by: AndyH on 2008-Feb-04
I've some code that

* draws a rectangle using the transparent color -RGB(255,0,128)
* draws a sprite into that area
* does a grab sprite
* THEN draws this grabbed sprite using ZOOMSPRITE

I get a purple halo around the image where transparent and non-transparent colours meet, included the outer border of the sprite.  I reported this problem as part of another post which was buried and I forgot about it until coming across it again now.

Code (glbasic) Select
// sprite loaded in Id=1
DRAWRECT 0,0, 32, 32, RGB(255,0,128) // transparent colour
DRAWSPRITE 1,0,0
GRABSPRITE 1,0,0,32,32

ZOOMSPRITE 1, 100,100, 2,2
Here's a examples:

(http://baa.ovine.net/glb/ZOOMSPRITE.png)

(http://baa.ovine.net/glb/scale.png)

It doesn't do it if you only do LOADSPRITE, the problem occurs after doing a drawsprite then grabsprite.  Can this please be fixed.
Title: GRABSPRITE on transparent color problem with ZOOMSPRITE/STRETCHSPRITE
Post by: AndyH on 2008-Feb-04
Ah, should add that ROTOSPRITE and ROTOZOOMSPRITE does it as well.  Only vanilla DRAWSPRITE will draw the grabbed sprite without putting the purple outline around everything.
Title: GRABSPRITE on transparent color problem with ZOOMSPRITE/STRETCHSPRITE
Post by: Kitty Hello on 2008-Feb-04
Oh dear. Could you set RGB(0,0,0) as transparent color, maybe :D (duck+run)

The problem is, that OpenGL slighty blends the neighbour pixels (pink) into your grabbed image. I might improve it, but it could slow down things horribly, since I'd have to check pixel by pixel for transparent color.
Title: GRABSPRITE on transparent color problem with ZOOMSPRITE/STRETCHSPRITE
Post by: AndyH on 2008-Feb-04
OK, I'll check that.  There's a command to change what is the transparent colour - does this change globally for DRAWSPRITE or does it affect GRABSPRITE only?  (I haven't got GLB here at work to check)
Title: GRABSPRITE on transparent color problem with ZOOMSPRITE/STRETCHSPRITE
Post by: Kitty Hello on 2008-Feb-04
only Grabsprite and loadsprite.
Title: GRABSPRITE on transparent color problem with ZOOMSPRITE/STRETCHSPRITE
Post by: AndyH on 2008-Feb-04
Great, I'll see if that works for me later :)
Title: GRABSPRITE on transparent color problem with ZOOMSPRITE/STRETCHSPRITE
Post by: AndyH on 2008-Feb-04
Hi Gernot,  I've tried using SETTRANSPARENT and it does improve things a tiny bit but I think there must be a problem.

Take a look at this (i've made this screenshot 300% the size it normally is):

(http://baa.ovine.net/glb/grabsprite2.png)

All of these sprites have been grabbed using GRABSPRITE apart from one of the 'v's and then I've used either DRAWSPRITE, ZOOMSPRITE or ROTOZOOMSPRITE to display them at different sizes.

Notice the Boxed 'O' has no transparency and looks as I expect it to (yes it's blurred a bit due to scaling it up).

Now look at the N and the bottom larger V.  I;ve GRABSPRITE'd these from a black background now, with black as the transparent colour.  They have a black outline much like the purple one I had before with the default transparent colour.

Now take a look at the top V that is scaled up.  This is my original image of the V where I have just used LOADSPRITE and nothing else (no GRABSPRITE on this one).  The non-transparent areas are blurred as expected, but the transparent regions remain transparent, right up the the edges of the V.

Look at the bottom V, this has been GRABSPRITE'd and displayed in exactly the same way as the top V, only it suffers from a black border.

What I don't understand is when I do a GRABSPRITE the image of the V is identical to the LOADSPRITE original.  It is identical on screen - there is no blurring or anti-aliasing around the edges, so I would expect GRABSPRITE to get an exact copy of the V and be no different to the LOADSPRITE original - so why is it not?

For comparison I have drawn the V from the LOADSPRITE version and the GRABSPRITE version at normal scale to the upper right of that screenshot.  Can you tell which one is which?  I can't.  I've checked in photoshop too, and there is no difference.

Why can't / doesn't GRABSPRITE work the same as LOADSPRITE in this case?  The image I load has no alpha information, it's just got a transparent colour.  I've linked to the images used below.

This screenshot is from my larger project, so I'll put together a small example later just to make sure I haven't done something wrong in my code.  But it does appear to be a bug in GRABSPRITE...


Images used to generate that screenshot:

(http://baa.ovine.net/glb/v.png)
(http://baa.ovine.net/glb/ovine.png)
Title: GRABSPRITE on transparent color problem with ZOOMSPRITE/STRETCHSPRITE
Post by: AndyH on 2008-Feb-05
Here's the code:

Code (glbasic) Select
SETSCREEN 320,240,0
LIMITFPS 60

// normal sprite in 0
LOADSPRITE "v.png",0


// Grab sprite on purple trans in 1
SETTRANSPARENCY RGB(255,0,128)
DRAWRECT 0,0, 32,32, RGB(255,0,128)
DRAWSPRITE 0,0,0
GRABSPRITE 1,0,0,32,32


// Grab sprite on black trans in 2
SETTRANSPARENCY RGB(0,0,0)
DRAWRECT 0,0, 32,32, RGB(0,0,0)
DRAWSPRITE 0,0,0
GRABSPRITE 2,0,0,32,32


BLACKSCREEN

DRAWRECT 10,10,20,230, RGB(120,0,0)
DRAWRECT 50,10,20,230, RGB(120,0,0)

// sprite 0 normal and large
PRINT "Normal sprite 0",0,0
DRAWSPRITE 0,0,5
PRINT "Zoom sprite 0",50,7
ZOOMSPRITE 0,50,20,2,2

// sprite 1 normal and large
PRINT "Purple sprite 1",0,50
DRAWSPRITE 1,0,55
PRINT "Zoom sprite 1",50,57
ZOOMSPRITE 1,50,70,2,2

// sprite 2 normal and large
PRINT "Black sprite 2",0,100
DRAWSPRITE 2,0,105
PRINT "Zoom sprite 2",50,107
ZOOMSPRITE 2,50,120,2,2


SHOWSCREEN
MOUSEWAIT
You need that v.png image in the previous post.

Run on PocketPC (no OpenGL intervention I guess) and all six 'V's look the same.

Run on Windows and the first two look as I'd expect, next two with the purple halo and final two with black halo.  The halo parts of the image are part transparent pixels and part actual sprite pixels - so it is destroying the image at these edges, not just putting a halo around it.

Can this be fixed?  Grabsprite is not very useful in it's current state.  I'm using GRABSPRITE because the ANIM functions for ZOOM, STRETCH, ROTATE, ROTOZOOM etc are not available yet.  I can't use tilesets and then GRABSPRITE them into separate sprites so I can use the SPRITE ZOOM/STRETCH/ROTATE etc if the images are altered in this way.
Title: GRABSPRITE on transparent color problem with ZOOMSPRITE/STRETCHSPRITE
Post by: Kitty Hello on 2008-Feb-05
OK, there's 2 fixes for you.
I'll implement ROTOZOOMANIM, that's the easiest solution.
If you want to scale grabbed gfx, then OpenGL also uses pixels at the border and mixes their color in (take 25% from border pixel + 50% from best pixel + some from the neighbours).
If you want to disable this, you can set it to linear mode:
Code (glbasic) Select
}
extern "C" void __stdcall ::glTexParameteri(int, int, int);
glTexParameteri(0x0de1, 0x2800, 0x2600); // GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(0x0de1, 0x2801, 0x2600); // GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
namespace __GLBASIC__{
Then your scaled images also look blocky as on GP2X/PocketPC.
Note, this is just for informaton - don't do it.

So for now, stay with it until I finished zoomani, or save each piece as a different sprite.
Title: GRABSPRITE on transparent color problem with ZOOMSPRITE/STRETCHSPRITE
Post by: AndyH on 2008-Feb-05
Thank Gernot

RotoZoomAnim will atleast allow me to keep all my anims together :)  What's the deal with GRABSPRITE though?

On my PC the loaded sprite when scaled up does not 'take 25% from border pixel + 50% from best pixel + some from the neighbours', only the grabbed sprite versions do that.  Meaning Loaded sprites do look blobky on the edges, not smoothed.  Does this not happen on your OpenGL card?

Thanks for looking into this.
Title: GRABSPRITE on transparent color problem with ZOOMSPRITE/STRETCHSPRITE
Post by: Kitty Hello on 2008-Feb-05
Yes. OpenGL does smooth texture texel interpolation, resulting in smoothed images, when scaling bigger than factor 1.0.
In PocketPC (my own library) I use "take the closes pixel" approach, which results in blocky scalings, but offer more speed. (would be unusable on small devices otherwise).
Title: GRABSPRITE on transparent color problem with ZOOMSPRITE/STRETCHSPRITE
Post by: AndyH on 2008-Feb-05
QuoteYes. OpenGL does smooth texture texel interpolation, resulting in smoothed images, when scaling bigger than factor 1.0.
This doesn't happen on my PC in Windows (Vista) with a LOADSPRITE'd version though... that's the bit I don't understand:

Code (glbasic) Select
LOADSPRITE "v.png",0
DRAWSPRITE 0,0,5   // sprite at normal size
ZOOMSPRITE 0,50,20,2,2 // sprite at double size - transparent edges are not blurred
This scales up, there is no alteration of the border of visible pixels with the pixels that are transparent.

This code however ...

Code (glbasic) Select
SETTRANSPARENCY RGB(255,0,128)
DRAWRECT 0,0, 32,32, RGB(255,0,128)
DRAWSPRITE 0,0,0
GRABSPRITE 1,0,0,32,32
... draws the sprite at normal scale on the purple background.  I've taken a snapshot of this and compared it to the original image in photoshop and all pixels are exactly the same colour values.  I then GRABSPRITE into sprite 1 and draw this with ZOOMSPRITE and it looks different:

Code (glbasic) Select
ZOOMSPRITE 0,50,20,2,2
ZOOMSPRITE 1,150,20,2,2
Sprite 0 and sprite 1 are displayed differently.  Sprite 0 has no blurring or color distortion on edges with transparent colours, but sprite 1 does.

BTW - there's no alpha channel on the original LOADSPRITE'd image, so I'd expect sprite 0 and sprite 1 to look the same.

I want sprite 1 to look like sprite 0.   That's the bit I don't get.

This is how it looks in Windows (compare the two enlarged V letters):

(http://baa.ovine.net/glb/grabsprite2.png)
Title: GRABSPRITE on transparent color problem with ZOOMSPRITE/STRETCHSPRITE
Post by: AndyH on 2008-Feb-05
QuoteThen your scaled images also look blocky as on GP2X/PocketPC.
Note, this is just for informaton - don't do it.
BTW - having a command to choose blocky or smoothed for Win/Mac/Linux would be nice to have - sometimes in 2D games you might not want OpenGL to render the image smoothed, but in textures for 3D of course you probaly always do.

Could this be toggled at runtime to affect drawing operations at will such as ALPHAMODE does or is it a property that can only be set when the texture is loaded?
Title: GRABSPRITE on transparent color problem with ZOOMSPRITE/STRETCHSPRITE
Post by: Kitty Hello on 2008-Feb-06
You can change that at runtime. Well, might be an idea.
Title: GRABSPRITE on transparent color problem with ZOOMSPRITE/STRETCHSPRITE
Post by: AndyH on 2008-Feb-06
Sounds like a good option to have, for when it's needed (epsecially when doing retro - or when scaling up the 320x240 screen to 640x480 when your monitor doesn't support the lower full screen resolution and you want to scale up without the blurring).  Please could you add that command?

So are you able to fix the issue seen here, it's quite important to be able to grab and display consistent to the original image:

Code (glbasic) Select
LOADSPRITE "v.png",0
SETTRANSPARENCY RGB(255,0,128)
DRAWRECT 0,0, 32,32, RGB(255,0,128)
DRAWSPRITE 0,0,0
GRABSPRITE 1,0,0,32,32

ZOOMSPRITE 0,50,20,2,2  // original - no edge blurring
ZOOMSPRITE 1,150,20,2,2 // GRABSPRITE version - bluring on edges
Title: GRABSPRITE on transparent color problem with ZOOMSPRITE/STRETCHSPRITE
Post by: Kitty Hello on 2008-Feb-14
To be honest... No, I don't see a way other than using the INLINE i showed you.
Title: GRABSPRITE on transparent color problem with ZOOMSPRITE/STRETCHSPRITE
Post by: AndyH on 2008-Feb-15
You're kidding?  Something's wrong with grabsprite surely?

A work around is to do this:

Code (glbasic) Select
// load the original sprite
LOADSPRITE "v.png",0

// do a grabsprite
SETTRANSPARENCY RGB(255,0,128)
DRAWRECT 0,0, 32,32, RGB(255,0,128)
DRAWSPRITE 0,0,0
GRABSPRITE 1,0,0,32,32

BLACKSCREEN

// Sprite 0 will be drawn correctly when scaled/rotated, sprite 1 has changed
ZOOMSPRITE 0,50,0,2,2
ZOOMSPRITE 1,150,0,2,2

// this saves the grabbed sprite back to a temporary file and load back in again
SAVESPRITE "x.png", 1
LOADSPRITE "x.png",1

// Sprite Id=1 now displays correctly when zoomed or rotated
ZOOMSPRITE 0,50,70,2,2
ZOOMSPRITE 1,150,70,2,2

SHOWSCREEN
Saving the grabbed sprite and loading it back in solves the problem.  Not very elegant but works.  I still don't understand why you would want the grabsprite version to be displayed differently.
Title: GRABSPRITE on transparent color problem with ZOOMSPRITE/STRETCHSPRITE
Post by: AndyH on 2008-Feb-15
Hmmm, with my test image (the v.png above) it does solve the problem.

However if I draw some single width lines on that v.png image, when scaled these lines get a black border around it, similar to what I was seeing after a grab sprite but the rest of the image is not distorted in this way.  *scratches head*  The way Open GL is drawing a sprite scaled up or rotated or the way GLBasic is doing it?


First question.  How do I use that INLINE code above?  Better still - can you give us a function to put into that mode, so that the image is not filtered when scaled ie: It will look the same as it does on Pocket PC and GP2X?

Second question.  Can you improve the way the transparent colour is drawn (or ignored) when scaled and/or rotated?

Here's some BMax code:

Code (glbasic) Select
Framework BRL.GLMax2D
Import brl.Retro
Import BRL.PNGLoader
Import BRL.BMPLoader

SetGraphicsDriver GLMax2DDriver()

Graphics 640,480
SetMaskColor 255,0,128
spr = LoadImage ("v2.png", MASKEDIMAGE | FILTEREDIMAGE)

Local a=0

Repeat
Cls
SetScale(2,2)
DrawImage spr, 10,10
Flip True
Until a=1
This draws the sprite at double the size, using OpenGL but there are no issues with scaling.

Here's a comparison drawing the same image in GLBasic and BMax at double size.  The top images from GLBasic (you can see the unscaled versions next to the scaled versions).  The bottom image is from BMax.

(http://baa.ovine.net/glb/comparison.png)

Note that in the code, BMax allows me to load the image in with the FILTEREDIMAGE flag.  This renders it smoothed out like GLBasic does, but the transparent color and the neighbours to transparent colors are drawn as I'd expect.  In GLBasic it corrupts the image.  I think scale and rotation in GLBasic on OpenGL platforms are unusable.  Sorry but this is an issue.

Note also in BMax, if you exclude the FILTEREDIMAGE flag when loading the image, it is drawn using nearest neighbour (meaning blocky).  This is a nice option to have for 2D games.  Other flags allow you to load in the alphachannel of an image to use as transparency which GLBasic handles automatically.
Title: GRABSPRITE on transparent color problem with ZOOMSPRITE/STRETCHSPRITE
Post by: AndyH on 2008-Feb-15
(http://baa.ovine.net/glb/comparison.png)
BTW - GLBasic seems to give the hard edge to the V image which is what I have been seeing while testing.  This is consistent with the BMax version of the code displaying same image.  For the V shape itself it only differs with that last bit of the V at the top right.

It's the black horizontal and vertical lines under the V and the light coloured flicks off the edge of the V that GLBasic is changing.  This is very noticeable with my real sprites in my game.   I'm just making certain sprites pulsate in size slightly larger/smaller than the default size but they distort so much on their transparent borders that it looks really bad.

The way GLBasic renders scales/rotated sprites in Open GL mode really needs addressing. :wah:

Drawing sprites at normal size has given me no issues at all.
Title: GRABSPRITE on transparent color problem with ZOOMSPRITE/STRETCHSPRITE
Post by: Kitty Hello on 2008-Feb-15
OK. I've implemented a new command: SMOOTHSHADING, which affects all following 2D sprite commands.
You can use it for rotozoom something when you want it blocky and the pink border should be gone, too.
I also tried loading and saving a sprite, which worked both PNG/BMP well.
Here's my sample program. I hope that fixes all issues then.
Code (glbasic) Select
DRAWRECT 0,0,129,65,RGB(255,0,128)
PRINT "test", 1,0
DRAWRECT 1,16,64,16,RGB(255,0,0)
DRAWRECT 1,32,64,16,RGB(0,255,0)
DRAWRECT 1,44,64,16,RGB(0,0,255)

GRABSPRITE 0, 0,0,128,64
DRAWRECT 160,0,160,240,RGB(255,255,255)

DRAWSPRITE 0, 162,2
SAVESPRITE "out.png", 0
LOADSPRITE "out.png", 0


ROTOZOOMSPRITE 0, 40,80, 45, 1.5
SMOOTHSHADING FALSE
ROTOZOOMSPRITE 0, 200,80, 45, 1.5


SHOWSCREEN
MOUSEWAIT
Title: GRABSPRITE on transparent color problem with ZOOMSPRITE/STRETCHSPRITE
Post by: AndyH on 2008-Feb-15
That sounds just the job.  Thanks.
Title: GRABSPRITE on transparent color problem with ZOOMSPRITE/STRETCHSPRITE
Post by: AndyH on 2008-Feb-15
Got latest update.  You Star!

Now my scaled / rotated graphics look great in 2D.  Gives me the same result as spr = LoadImage ("v2.png", MASKEDIMAGE).

Many thanks for the quick turn around, I spent hours last night trying to lessen the impact that this smoothing on the transparent pixels was having in the Windows version so this fix is much appreciated.
Title: GRABSPRITE on transparent color problem with ZOOMSPRITE/STRETCHSPRITE
Post by: Kitty Hello on 2008-Feb-15
Wahoo!
So, the ToDo list is slowly shrinking now ;)
Title: GRABSPRITE on transparent color problem with ZOOMSPRITE/STRETCHSPRITE
Post by: AndyH on 2008-Feb-15
One last thing, it looks like you must call SMOOTHSHADING FALSE every SHOWSCREEN otherwise it reverts to SMOOTHSHADING TRUE .  Is this intentional or a bug?
Title: GRABSPRITE on transparent color problem with ZOOMSPRITE/STRETCHSPRITE
Post by: Kitty Hello on 2008-Feb-15
See the manual ;)
Yes, a SHOWSCREEN, X_MAKE2D or X_MAKE3D resets all states to initial values.
Title: GRABSPRITE on transparent color problem with ZOOMSPRITE/STRETCHSPRITE
Post by: AndyH on 2008-Feb-15
RTFM - hehe - yes, should have looked there.  Thanks for the info and this fix :)