Prev: Simple Obfuscation
Next: Flag test
From: Bee on 14 Mar 2010 15:32 Still working with sprites. Well ... trying. I have an image (i call it a positive for lack of a better definition) that I want to make into a sprite. I then need to create the sprite mask (the mask). The positive is picture and not necessiarly line art (that would be simpler). I copy the positive to the mask for starters. Using all bitmaps .BMP to preserve them. So I need to have show through areas in the sprite. Current thinking is that the positive needs to have pure black in the transparency area. So i hand draw the black. Now the mask needs these same areas to be white so I replace all black with white. unfortunately, there are some black areas originally in the positive that I do not want to be transparent. i have no contol over the colors in the image except for hand drawing the transparency areas. (1) is there an easy way to fix this? (2) am I limited to black and white for the positive and mask transparency area? I have tried to use other colors but it did not work. e.g. for the positive i use red and for the mask i use the bitwise complement color. I guess I do not understand that the BitBlt is doing with the SRCAND and SRCPAINT I am thinking that i could preprocess the positive and change all black to almost black (off by one bit). then the black (positive) to white (mask) would only change the transparency area and the almost black would not be detectable by eye. Or it I could get colors oter that black and white to work, i could choose a colr not in the positive. seems like too much work on this thought.
From: Larry Serflaten on 14 Mar 2010 20:55 "Bee" <Bee(a)discussions.microsoft.com> wrote > So I need to have show through areas in the sprite. > Current thinking is that the positive needs to have pure black in the > transparency area. > So i hand draw the black. > Now the mask needs these same areas to be white so I replace all black with > white. The mask needs to be white where you want transparency, and black where you want the positive to show. Where there is black in the positive image that you want to show, that area has to be black in the mask. So you can not simply 'replace all black with white', but must replace only the opaque areas with black. To see an example, paste the following into a new form: LFS Private Sub Form_Load() AutoRedraw = True ScaleMode = vbPixels ' Positive Line (0, 0)-(50, 50), 0, BF DrawWidth = 7 Circle (25, 25), 18, vbRed Line (15, 36)-Step(20, -20), vbRed DrawWidth = 1 ' Mask Line (60, 0)-(110, 50), vbWhite, BF DrawWidth = 11 Circle (85, 25), 18, vbBlack Line (75, 36)-Step(20, -20), vbBlack DrawWidth = 1 ' Background image Line (0, 100)-(110, 150), vbYellow, BF PSet (5, 115), vbYellow Font.Size = 16 Font.Bold = True ForeColor = vbBlue Print "EXAMPLE" Picture = Image ' Sprite copy PaintPicture Me.Picture, 30, 100, 50, 50, 60, 0, 50, 50, vbSrcAnd ' Mask PaintPicture Me.Picture, 30, 100, 50, 50, 0, 0, 50, 50, vbSrcPaint ' Positive End Sub
From: Bee on 14 Mar 2010 20:45 Well, except when I google I see where it talks about using other colors. So are they doing something different? Terminology limited here so it is all still a little confusing. I have my code set up to do black and white but was considering alternatives. What I have works for the case where black and white are NOT in the original sprite. Some images already have those as areas of non-transparency. "Larry Serflaten" wrote: > > "Bee" <Bee(a)discussions.microsoft.com> wrote > > > So I need to have show through areas in the sprite. > > Current thinking is that the positive needs to have pure black in the > > transparency area. > > So i hand draw the black. > > Now the mask needs these same areas to be white so I replace all black with > > white. > > > The mask needs to be white where you want transparency, and black where > you want the positive to show. > > Where there is black in the positive image that you want to show, that > area has to be black in the mask. So you can not simply 'replace all > black with white', but must replace only the opaque areas with black. > > To see an example, paste the following into a new form: > > LFS > > > Private Sub Form_Load() > AutoRedraw = True > ScaleMode = vbPixels > > ' Positive > Line (0, 0)-(50, 50), 0, BF > DrawWidth = 7 > Circle (25, 25), 18, vbRed > Line (15, 36)-Step(20, -20), vbRed > DrawWidth = 1 > > ' Mask > Line (60, 0)-(110, 50), vbWhite, BF > DrawWidth = 11 > Circle (85, 25), 18, vbBlack > Line (75, 36)-Step(20, -20), vbBlack > DrawWidth = 1 > > ' Background image > Line (0, 100)-(110, 150), vbYellow, BF > PSet (5, 115), vbYellow > Font.Size = 16 > Font.Bold = True > ForeColor = vbBlue > Print "EXAMPLE" > Picture = Image > > ' Sprite copy > PaintPicture Me.Picture, 30, 100, 50, 50, 60, 0, 50, 50, vbSrcAnd ' Mask > PaintPicture Me.Picture, 30, 100, 50, 50, 0, 0, 50, 50, vbSrcPaint ' Positive > > End Sub > > > > > > . >
From: Mike Williams on 15 Mar 2010 05:55 "Bee" <Bee(a)discussions.microsoft.com> wrote in message news:C3439316-471D-456C-A5A7-00FE744AB8F4(a)microsoft.com... >> "Larry Serflaten" wrote: >> The mask needs to be white where you want transparency, >> and black where you want the positive to show. > > [Bee responded] Well, except when I google I see where it talks > about using other colors. So are they doing something different? > I have my code set up to do black and white but was considering > alternatives. What I have works for the case where black and > white are NOT in the original sprite. Some images already have > those as areas of non-transparency. What Larry was talking about is the colours of the prepared mask and the prepared sprite image (the two things that you need to effectively combined together into the destination in order to perform a transparent blit). There are slightly different arrangements (white on black instead of black on white etc) depending on the specific raster operations you use in the two blits, but the "black on white" mask and the "colour on white" sprite image is possibly the most commonly used arrangement, and if you prepare those two things in such a manner then you can perform your transparent blit into the destination by first blitting the prepared "black on white" mask into the destination using vbMergePaint, which effectively "punches a white hole" the shape of the black portion of the mask into the destination, followed by a blit of the prepared "colour on white" sprite image using vbSrcAnd at exactly the same place in the destination, which (because of the presence of the "white hole we just punched") effectively draws only the coloured pixels of the prepared "colour on white" sprite image into the destination whilst not drawing the white pixel of the prepared "colour on white" sprite image at all. So, Larry was telling you what you need to do with regards to creating the required mask and image (a "black on white" mask and a "colour on white" sprite image). Those are the two images you need, but both of them need to be "made" using the data of your original picture or drawing. They can either be made manually (as you currently appear to be doing) or they can be made in code by your program. The rest of the story (exactly why the two blits mentioned above do what I've told you they do, and the details of how those two images can be made in and why sometimes one method is better than the other) can be told in many different ways, depending mainly on whether you simply want a routine which works and which you can use in your own code or whether you would prefer to actually learn "why these things work". Reading your original post I'm not quite sure which of those two things you would prefer. > Well, except when I google I see where it talks > about using other colors. So are they doing > something different [2]? That depends on what you've been Googling. You'll find lots of routines that draw images transparently, and in many cases they will be starting with an original image (your original drawing or picture or whatever) and they will be using one or more different methods to construct the "black on white mask" and the "colour on white" sprite image that I mentioned in the above paragraph. Such routines construct those two images from the original image (your original drawing or whatever) and then they use them to actually perform the transparent blit, usually in the way I have already described above. The part of the routine that constructs the mask and the sprite image in code from your original drawing or picture is usually written in such a way that it will accept any colour you wish as the desired "transparent colour" when they are constructing the mask and the sprite. For example, if you have an original picture and you pass it to such a routine then you will be able to specify any colour you wish as the desired "transparent" colour. That's probably the sort of stuff you've been Googling. Passing your original picture to such a function will draw the sprite transparently for you, but (because it needs to create the mask and sprite images "on the fly" as part of the job it is doing) it will not be as fast as if you had prepared the "black on white" mask and "colour on white" sprite image in advance yourself (either manually or in code) and then just used those two images in two BitBlt functions as mentioned above each time you need to draw the transparent image at any specified position. Anyway, the details of how these routines actually work and how you can do them yourself would probably best be left until you have answered the question I asked in the first paragraph above, and I'm sure you will get lots of responses from lots of people here. By the way, whilst you are deciding what sort of responses you would like, I might just mention one specific API function that is capable of doing the entire job for you, so as far as you are concerned there is virtually no work at all for you to do. The function does all the various things I have been talking about "under the hood" and all you need to do is pass it your original picture or drawing and tell it what colour you would like to use as the transparent colour and it will then draw the sprite transparently for you, effectively "all in one go" as far as the coder is concerned. It is the TransparentBlt function in msimg32.dll. Normally I would not mention that at all, and normally it is the very last thing I would consider using, partly because it used to have a bad memory leak and partly because it used to be very much slower than doing the same job using two Blits with ready prepared mask and sprite images. However, things have changed a lot since Vista arrived (for the worse!). The memory leak was fixed in Windows XP onwards (a good thing) and Vista has totally crippled GDI32 (a bad thing!), so much so that in Vista performing two blits on ready prepared mask and sprite images (which used to be very much faster than using the TransparentBlt API) is now actually about the same speed, or even a bit slower! Vista really does make me angry! Anyway, if you decide that you would rather just have some working code and that you do not actually want to learn how these things work (and of course if you are only concerned with performing this job on Vista machines) then you might like to have a look at the API TransparentBlt function in msimg32.dll. It really is very easy to use, and you should find lots of working examples on Google. Post again if you want to go that way and if you would like example code. Mike
From: Larry Serflaten on 15 Mar 2010 09:03
"Bee" <Bee(a)discussions.microsoft.com> wrote > Well, except when I google I see where it talks about using other colors. > So are they doing something different? See Mike's response for TransparentBlt which could be what you've seen > Terminology limited here so it is all still a little confusing. > I have my code set up to do black and white but was considering alternatives. > What I have works for the case where black and white are NOT in the original > sprite. Some images already have those as areas of non-transparency. Your first post mentioned using SRCAND and SRCPAINT so that is the method I posted. It works for any / all available colors in the 'positive' image. If you noticed, the red symbol had a black outline. If you want to see it also using white, make the change below to the earlier posted example: > > ' Positive > > Line (0, 0)-(50, 50), 0, BF > > DrawWidth = 7 > > Circle (25, 25), 18, vbRed > > Line (15, 36)-Step(20, -20), vbRed ' < < Change to vbWhite > > DrawWidth = 1 You'd then have a red circle with a white diagonal line, all outlined with black. As I said, any available color in the 'positive' will work, as long as that area is black in the mask image. If you want to understand how it works, it may help to think of the bit values of the colors you are using. The mask is black (no bits on) on white (all bits on). Whenever you AND the mask to whatever colors, the black area ANDed with any color results in black, where the white area ANDed with any color results in the original color. After copying the mask to the destination you get a black image on the destination matching the opaque area of the positive image. You can then OR the positive image where anything ORed with black results in the original color. Comment out those PaintPicture lines (one at a time), to see what they do.... HTH LFS |