How can I draw text on a TImage and retain Alpha?
BlitzMax Forums/BlitzMax Programming/How can I draw text on a TImage and retain Alpha?
| ||
Hi. I have an image of a scroll which is a png so the edges are alphablended and there are full transparent areas too. I'd like to draw some text onto the scroll but I have no idea how to do this! I could cls the screen, draw the scroll, then the text, then regrab the whole thing but then the grabbed image will have no alpha data so I won't be able to use it properly in-game anymore... So is there a way to draw text directly (using DrawText) onto an image using maybe Pixmaps or some DirectX render to texture jiggery pokery? I'm using draw text because the actual text changes all the time, I can't predraw it outside of the game. Any advice much appreciated. Thanks :-) |
| ||
didn't know grabimage lost alpha data :o. hmmm, I know blitzplus allowed this to be solved easily where in bMax it takes a little more effort. Alot of times if I want combined images I just make a type with a custom render() method that just renders each part inidivually but keeps them relative to each other. Would that work or do you specifically need the image to contain the text in its pixels? |
| ||
Why not draw the scroll, draw the text, grab a rectangular portion of the scroll containing the text but not the transparent bits? |
| ||
Alex O. well I haven't tested it, but it MUST loose transparency as soon as it's drawn you see. Tonyg, ah yes good plan, thanks! Will work well unless I have wide text say at the top of the scroll, and the middle of the scroll curves in more than the wide text at the top. So in principle the question still remains for general use even though it's solved for my use for now... |
| ||
There's this... Pixmap paste with mask although it's not quick for large images. RTT is a possibility. For the wider than the top stuff can't you... 1) Draw rectangle with, for example, colour 255,0,255 2) Draw the text 3) Grab the area of text. 4) Setmaskcolor 255,0,255 5) Loadimage the text. 6) Draw Scroll 7) Draw Text image. |
| ||
tonyg: Thanks. I do need to predraw each frame so the pixmap paste with mask could be a bit slow I guess. As for the other idea it sounds viable except that the text is normally drawn with alphablend onto the scroll for nice edges and wouldn't that mask technique result in a hard edge? |
| ||
How often will you be changing the text? How much text is there? How big is the scroll? How often will the scroll move? How many ms do you have to work with? How about posting some code pointing out what you want to improve? How about using a bitmap font system where your font is created over a transparent background? How about using DX multitexturing? What about the Tim's RTT module? |
| ||
well like I said for me your first solution will work. I was just wondering for the future if it would be possible to have an irregular shaped image and draw text on it retaining all alpha (text/image) without using a viewport, but I guess you could draw each line of text and capture each line in separate rectangle of course. Looks liek I'll also have to look into RTT soon as I still haven't done it. |
| ||
If your display is 32-bit color, and only that mode, your grabbing of the image should copy the alpha channel as well. Otherwise there is no alpha to grab in the destination. At least in GL you can draw to a 32-bit screen that has an alpha channel, using a 32-bit scroll image with alpha, but as `solidblend` and with alpha channel enabled. Then draw the text the same. Then glcopyTexsubimage2d() would copy it back into the texture as RGB with alpha. I don't know how you'd do it in direct x. You have to have some way of drawing the alpha, from both sources, into the alpha of your destination, whether its the backbuffer or the original texture. Using pixmaps you can do a custom copy routine which does an ADD on the alpha channel and a REPLACE on the RGB channels. Might need to divide the alpha by 2. Or make a `combiner` routine, takes the two sources and outputs to a third pixmap that you use to draw with. OR you can just have two images. Your original scroll image, render your text to another image with alpha channel, then just drawimage twice. ???? |
| ||
Still can't se why you can't draw the text to a black screen, grab it into an image and then draw them both. Rubbish example but it might give you an idea. Graphics 640 , 480 SetColor 200 , 150 , 150 DrawRect 0 , 0 , 400 , 400 image:TImage = LoadImage(GrabPixmap(0 , 0 , 400 , 400)) Cls SetColor 0 , 0 , 0 DrawRect 0 , 0 , 400 , 400 SetColor 255 , 255 , 255 DrawText "Hello World" , 100 , 100 image2:TImage = LoadImage(GrabPixmap(0 , 0 , 400 , 400) ) SetClsColor 255,0,0 Cls DrawImage image , 150 , 0 DrawImage image2 , 0 , 0 Flip WaitKey() p.s. the text can be drawn with a bitmap font with transparent background... I think. |
| ||
AngelDaniel@ Oh, so a 32-bit display retains alpha information, I should have realised that. Hmm, the only problem is my game may start in 16 bit mode if 32 mode cannot be found on the PC, so I can't rely on that :-( Also if it's in windowed mode the desktop could be at 24bit or 16bit of course. Tonyg: Because I'm drawing in a bigger font with alpha blend on for smooth edges and if I do that on black then grab it and redraw on an image, it'll have a dark outline round the text instead of blending with the underlying image. |
| ||
ahhh OK so I'd go back to having a seperate image for the scroll paper and the edges. |
| ||
yeah I think that solution was a winner for it's simplicity (which I couldn't see haha) |
| ||
Altough this thread is 3 years old, I have now the same problem. Since DrawText is pretty slow compared to the other Draw functions i intended to precache frequently used texts as an image. Right now, i create this image kinda like this: TextImage = CreateImage(TextWidth(Text) , TextHeight(Text)) SetColor(0,0,0) ; DrawRect(0 , 0 , TextWidth(Text) , TextHeight(Text)) SetColor(255,255,255) ; DrawText(Text,0,0) GrabImage(TextImage,0,0) But as stated in the posts above, the alpha-channel isnt "grabbed" (i suppose the backbuffer has no alpha-channel, which is understandable). Looking up the actual method of drawing the text, i quickly gave up due to the fact that the drawing is (of course) handled trough the driver, which i cant reconstruct (e.g. for pixmap use). So, same question - 3 years later - how do i draw text onto an image or pixmap? |
| ||
If you open a 32-bit screen the backbuffer DOES have an alpha channel. It's just a matter of whether blitz will transfer the alpha channel. Make sure to add ALPHA_BUFFER as a flag when opening your screen, then try it. |
| ||
Though the alpha_buffer flag does not work on all cards so if this is for BF targeted game, you potentially won't be able to use it due to their regular no end hardware requirements. |
| ||
Either this wont work or i'm just stupid and doing it wrong. I backed a little code with a sample font, and i got those nasty black borders, you can download it HERE You may notice that using the default (Null) Font dosnt produce any borders. Check it out. Hold L.Shift to toggle between using the created image or drawtext, you should clearly see the difference. |
| ||
I am shure that you can figure out the rest:Graphics 800,600 SetImageFont(LoadImageFont("Default.ttf" , 32)) Global font:timagefont = GetImageFont() Global g:TMax2DGraphics = tmax2dgraphics.Current() SetRotation 45 SetScale 4,4 draw("this is a test",300,300) Flip() WaitKey() Function Draw( text$,x#,y#) For Local i%=0 Until text.length Local n%=font.CharToGlyph( text[i] ) If n<0 Continue Local glyph:TImageGlyph=font.LoadGlyph(n) If glyph._image Local tx#=glyph._x*g.tform_ix+glyph._y*g.tform_iy Local ty#=glyph._x*g.tform_jx+glyph._y*g.tform_jy DrawImage glyph._image,x+tx,y+ty EndIf x:+glyph._advance*g.tform_ix y:+glyph._advance*g.tform_jx Next End Function use your own font or comment it out for the default BB font. this is really low level stuff so if Mark desides to modify the way the font module works this code will break. [edited] updated the code I just copied this from one of my files it contained unneeded instructions. |