Go Back  Xtreme Visual Basic Talk > Legacy Visual Basic (VB 4/5/6) > General > PlgBlt - Can you fake a monochrome bitmap?


Reply
 
Thread Tools Display Modes
  #1  
Old 12-29-2011, 10:45 PM
Zerocyde Zerocyde is offline
Freshman
 
Join Date: May 2007
Posts: 31
Default PlgBlt - Can you fake a monochrome bitmap?


I wanted to learn the rotation of images so I started learning about PlgBlt. I've got it down perfectly so far, except for using a transparency mask.

Code:
PlgBlt (destination imagebox).hDC, PointsArray(0), (source imagebox).hDC, X, Y, Width, Height, MaskSource, MaskSource X, MaskSource Y
I've been able to get it to work properly but only when the mask source is a picturebox with a monochrome bitmap loaded into it. Not just black and white, but you have to save the .bmp as monochrome.

The problem is, I have one picturebox where all of the images for my sprites are located, along with their masks. I want to pull the mask from THAT imagebox, but since the imagebox contains some non monochrome images, it wont work.

What would be the easiest way to pull a square out of an imagebox, and make the PlgBlt function think it's monochrome?

I was thinking maybe some sort of temporary bitmap variable or object I can dim, pull the square mask out of the picturebox full of images and store it in the temp object, convert it monochrome, and then use it as the argument for the PlgBlt function. Is there anything like that?

Psudo-Code Example:

Code:
Dim TempBitmap as Picture

TempBitmap = Bitmap(picture1.hdc, 30, 0, 30, 30) 'store the 30 by 30 mask square into tempbitmap

TempBitmap = Monochrome(TempBitmap) 'magic function to turn any Bitmap into monochrome

PlgBlt dest.hDC, PointsArray(0), source.hDC, 0, 0, 30, 30, TempBitmap, 0, 0 'PlgBlt transparent sprite with TempBitmap as the mask.

Last edited by Zerocyde; 12-29-2011 at 10:52 PM.
Reply With Quote
  #2  
Old 12-30-2011, 03:13 AM
surfR2911 surfR2911 is offline
Contributor
 
Join Date: Oct 2009
Posts: 719
Default Plgblt masking - monochrome and otherwise, and masked rotation

Quote:
I wanted to learn the rotation of images so I started learning about PlgBlt. I've got it down perfectly so far, except for using a transparency mask.
I've been able to get it to work properly but only when the mask source is a picturebox with a monochrome bitmap loaded into it.
Not just black and white, but you have to save the .bmp as monochrome.
I hate code snippets. You might just as well as referenced the AllAPI Plgblt page.

The fact is that if you do a search of the forum for the Plgblt API call you'll find only a handful of threads.

Hopefully, though, your working code is based on the code attached to this passel post.

Quote:
The problem is, I have one picturebox where all of the images for my sprites are located, along with their masks.
I want to pull the mask from THAT imagebox..
Wow..what an amazingly awkward (bad?) idea.

The mere thought of it gives me bad palletization code flashbacks.
Doing pixel color "thresholding" around a 127 for the black/white conversion,
working with DIBs and DIB to DDB conversions..definitely not my idea of "trivial" coding.

So all the sprite images and masks have to be combined...why?
..or in other words..
What horrible thing are you afraid is going to happen if they are not combined, (ie. handled separately, stored in separate controls)?

..um, maybe I should also add mention --there are other ways to do rotation besides using Plgblt.
I'm thinking of zelg37's Doldrums thread,
especially the attachment to this post.

I just tried downloading it again and the pathing to the form is messed up in the project.
So I fixed the project/form issue, added a graphic that might better show the masked rotation
and re-attached it (of course adjusting the angle slider setting at runtime does the rotation).
Attached Files
File Type: zip Mario_AlphaBlend-RotateScale.zip (52.5 KB, 18 views)

Last edited by surfR2911; 12-30-2011 at 04:17 AM.
Reply With Quote
  #3  
Old 12-30-2011, 10:54 AM
passel's Avatar
passel passel is offline
Sinecure Expert

Super Moderator
* Guru *
 
Join Date: Jun 2003
Location: Upstate New York, usa
Posts: 7,714
Default

Well, I believe there is a relatively simple way to create a monochrome bitmap from the black and white mask bitmap (involving creation of DCs and bitmaps and bitblting, etc), but I would have to test it before I would try to comment on how it would be done.

But, for speed, I prefer not to have to dynamically do things which could be done offline.
I understand you have a spritesheet with sprites and masks, which is not that uncommon.
My first impulse, which I have done in the past is, as VB6Oldguy mentions, to split the sprites and masks into different files, reorganizing how the sprite and mask offsets within the bitmaps are calculated.
But, if you have a lot of code that is based on the current offsets and you don't want to restructure everything, then a fairly simple compromise would seem to be, to load the spritesheet into Paint, and save it as a monochrome image to a new file.
Being as it is monochrome it will be 24 or more times smaller than the original image (unless it was compressed), but the point is to load the monochrome image as well as the original image into your program.
Then you can change your plgblt to reference the one bitmap for the image, and the other bitmap for the masks. You wouldn't have to change any of your offset calculations for sprite access. The main drawback, is your original bitmap is twice the size it needs to be because of the unused masks, and the monochrome bitmap is twice the size it needs to be, because of the "garbaged" unused, sprites.
But, it should be a quick fix.

P.S. I noticed OnErr0r looking at the thread, so he may give advice on the creation of a monochrome bitmap. I was going to look at code he's done in the past for a "programmatic mask" class as the basis for perhaps a scaled down version of just creating the monochrome image.

Also, I thought as far as using plgblt, the example in the 2nd post of this thread (ref. matrix3.zip) might be of some interest.
__________________
There Is An Island Of Opportunity In The Middle of Every Difficulty.
Miss That, Though, And You're Pretty Much Doomed.

Last edited by passel; 12-30-2011 at 11:08 AM.
Reply With Quote
  #4  
Old 12-30-2011, 03:54 PM
Zerocyde Zerocyde is offline
Freshman
 
Join Date: May 2007
Posts: 31
Default

Because of you two I got it solved and working flawlessly. Although a new issue has arisen.

Did the issue in this post http://www.xtremevbtalk.com/showthread.php?t=256204 ever get solved?

I get the exact same thing. Whenever my little dude is supposed to be EXACTLY upside down, the mask gets displayed right side up.
Reply With Quote
  #5  
Old 12-31-2011, 02:29 PM
Zerocyde Zerocyde is offline
Freshman
 
Join Date: May 2007
Posts: 31
Default

This is just silly. So, to temporarily make up for the magical inverse of the mask when rotating to an angle of 180, I added a second mask for each sprite, a 180 degree rotation of the regular mask, from its own .bmp file of course because plgbit is too sensitive to handle a mask rotated with code.

Worked fine, other than adding a ton more resources. Satisfied, I loaded up a new sprite from a different picture, and now it does the flipped mask at 270 degrees! The sprite with the first image doesn't, but this one does!

I really hope this is a known bug with an easy fix.
Reply With Quote
  #6  
Old 12-31-2011, 11:04 PM
passel's Avatar
passel passel is offline
Sinecure Expert

Super Moderator
* Guru *
 
Join Date: Jun 2003
Location: Upstate New York, usa
Posts: 7,714
Default

I guess if all you want to do is rotate, and you were willing to use plgblt, which only works on Windows 2000 and later, then perhaps instead of plgblt you might consider using another GDI call, SetWorldTransform, which was also added to the API at the same time plgblt was added.
SetWorldTransform uses a Matrix to allow the basic things you would need to position and rotate an image.
Basically you set up the matrix to translate the 0,0 point (rotation always occurs around the 0,0 point) to where in the destination you want the center of your image to be.
You put the sine and cosine of the angle in a few places in the matrix. (You don't have to understand why, just follow the pattern).
You then just draw or bitblt, etc.. and the drawing will be transformed by the matrix.
If you use SetWorldTransform then you wouldn't have to worry about monochrome bitmaps, etc. You can just use whatever technique your spritesheet required.

So, for an example, I've taken a small example I wrote recently that doesn't use a mask, per se, but draws the same image on a black background and white background, then uses bitblt with specific raster ops to draw the two images to a destination with "transparent" background.
A common misconception when first seeing the technique is thinking that it won't allow for White or Black in the image because it is using that for the background colors, but there is no "mask" color with this technique, so all colors can be used.
You can look at the vbSrcAnd raster op as transferring all the bits set to 0 to the destination image.
Likewise, you can look at the vbSrcPaint raster op as transferring all the bits set to 1 to the destination image.

So, with vbSrcAnd, the background is white, all 1's, no 0's, so none of the background is transferred to the destination (vbSrcAnd only transfers 0's). The 0's from your image are transferred because it has some 0's in it.
Any color other than white, has to have some 0's in it.

And, likewise with vbSrcPaint, the background is black (no 1's), so none of the background is transferred to the destination (vbSrcPaint only transfers 1's). But again, the 1's from the colors in the image are transferred (any color other than black will have some 1's in it).
So, if you have black (all 0's), you won't see it on the black background, but you will see it on the white background which is the image that 0's are transferred from, so black is drawn on the destination from the copy of the image.
Likewise, you won't see the white on a white background, but you will see it on the black background, which is the image use to transfer all the 1's.

Bottom line, you can use your normal techniques for doing your drawing, but let the matrix handle the tranforming of the points to accomplish the rotation.
You don't have to use the technique used in this example to implement the transparent background capability.

As I said earlier, the example attached is just a simple example based on one earlier. There are two pictureboxes at the top, one with a black background, the other with a white background.
When you click and drag on either one, a random color is chosen and a contiguous line is drawn in that color in both windows so that the image is the same in both windows.
At the same time, a timer is running which increments an angle value continuously from 0 to 360 degrees (in radians), and sets up a matrix, and bitblts the two images with the appropriate raster op into the lower picturebox.
So, the image you are drawing in the upper boxes, is continually rotating in the lower box.
Nothing practical, just another example of a way to do both transparent background and rotation of an image.
In your case, the rotation of the image is the primary thing to take away, as you already had the transparent background bitblting worked out with your spritesheet.

P.S. Once the matrix is set, it will effect all drawing to the hdc, even the drawing done by VB itself.
To see an example of it affecting VB's native drawing, add the following code to draw a grid either before or after the two bitblts, your choice (grid under the image or grid over the image). You will see the grid rotate as well.
Code:
    'Draw a grid
    Dim i As Single
    For i = -hs To hs + 4 Step (hs / 4)
      Picture2.Line (-hs, i)-(hs, i)
      Picture2.Line (i, -hs)-(i, hs)
    Next
P.P.S The dx,dy,px and py variables were left from the previous example, and are unused, so should be deleted.

Note, if you use the API Add-In that comes with VB6 to get your API declarations, it has the XFORM fields declared as doubles, which is incorrect. It didn't work well at all until I found that out.
Attached Files
File Type: zip DynamicTransparentRotateBlit.zip (28.6 KB, 37 views)
__________________
There Is An Island Of Opportunity In The Middle of Every Difficulty.
Miss That, Though, And You're Pretty Much Doomed.

Last edited by passel; 12-31-2011 at 11:47 PM.
Reply With Quote
Reply


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off

Forum Jump

Advertisement:





Free Publications
The ASP.NET 2.0 Anthology
101 Essential Tips, Tricks & Hacks - Free 156 Page Preview. Learn the most practical features and best approaches for ASP.NET.
subscribe
Programmers Heaven C# School Book -Free 338 Page eBook
The Programmers Heaven C# School book covers the .NET framework and the C# language.
subscribe
Build Your Own ASP.NET 3.5 Web Site Using C# & VB, 3rd Edition - Free 219 Page Preview!
This comprehensive step-by-step guide will help get your database-driven ASP.NET web site up and running in no time..
subscribe
 
 
-->