I wish to make a bitmap image (.bmp) transparent using VB.NET code. Kindly help me.
I found the key was using the imageAttributes class. Basically set the color key to the color you are using to represent the transparent area, and use one of the drawImage calls that accepts an imageAttribute parameter...
Imports System.Drawing.Imaging
' and in a sub somewhere:
Private mImageAttributes As New ImageAttributes
mImageAttributes.SetColorKey(Color.FromArgb(0, 220, 20, 255),
Color.FromArgb(0, 220, 20, 255))
Dim imageRectangle As New Rectangle(pX, pY, pBitmap.Width, pBitmap.Height)
e.Graphics.DrawImage(pBitmap, imageRectangle, 0, 0, pBitmap.Width, pBitmap.Height,
GraphicsUnit.Pixel, mImageAttributes)
VS 2012
Dim watermark_bm2 As Bitmap = 'someimage(from file or global resource)
watermark_bm2.MakeTransparent()
This msdn article gives full details on how to do this
Here is another article, but code sample is in c#
Related
I am making a 2D game in VB.NET. I use only one font object to draw strings on the form. This font is only needed in Game Menu. Therefore I dispose the font when it is not necessary and initialize it again when needed.
font_1 = New Font("Autobus Bold", 15.0)
When I use this font (font_1) to draw a string on the form, I get this error.
An unhandled exception of type 'System.ArgumentException' occurred in
System.Drawing.dll
Additional information: Parameter is not valid.
When I view the the font, it shows,
{Name = Reference to a non-shared member requires an object reference.
Size=15.0}
This error doesn't happen when the game menu is loaded for the first time (when font_1 is initialized for the first time). When the user plays the game, font is disposed. When user enters to Game Menu again, font is initialized again before it is used for drawing. When font is used for drawing a string on the window, this error happens.
It looks like error is only within the Font Family. I saw this question in few forums, but no one had given a solution. (This is my first question in a forum)
Edited : I removed the Font(font_1). But still I get the same error. Here is the code that draws the string.
Private Sub mcFramesHandler_TIMER_Tick(sender As Object, e As EventArgs) Handles mcFramesHandler_TIMER.Tick
gB.Clear(Color.Black)
gB.DrawImage(Background_IMG, 0, 0, 640, 480)
Select Case currentMode
Case GameMode.OnGame
If mcShoot_TIMER.Enabled Then gB.DrawImage(Bullet_IMG, Bullet_X, Bullet_Y, 20, 50)
If mcEneShoot_TIMER.Enabled Then gB.DrawImage(EneBullet_IMG, EneBullet_X, EneBullet_Y, 20, 50)
If Shooter_Lives Then gB.DrawImage(Shooter_IMG, Shooter_X, Bullet_Y_Def, 100, 105)
If mcMoveEnemy_TIMER.Enabled Then gB.DrawImage(Enemy_IMG, Enemy_X, 10, 100, 80)
If mcExplode_TMER.Enabled Then gB.DrawImage(Explotion_IMG, Explotion_X, Explotion_Y, 100, 80)
Case GameMode.Begining
gB.DrawString("Start", New Font("Autobus Bold", 15.0), textBrush(0), 110, 98) 'Error is generated in this line
gB.DrawString("Credits", New Font("Autobus Bold", 15.0), textBrush(1), 102, 158)
gB.DrawString("Exit", New Font("Autobus Bold", 15.0), textBrush(2), 114, 218)
End Select
Me.CreateGraphics.DrawImage(backbuffer, 0, 0, 640, 480)
End Sub
Here textBrudh(0) is a brush. gB is the Graphic object. gB successfully draws the background image before it draws the string. This happens only when Game Menu is displayed
Your support is really appreciated.
After you have finished to draw your things you need to dispose all objects around Graphics, not only the font but all (better with closure techniques like code below)
If you need a new instace of Graphics you can create this at the moment this is needed without using a Global object (when you work with Graphics).
Using gB As Graphics = Me.CreateGraphics
Using textBrush As Brush = Brushes.Black
Using font_1 As Font = New Font("Courier New", 15)
gB.DrawString("Start", font_1, textBrush, 400, 98)
'gB.DrawOtherthings()
'gB.DrawOtherthings()
'gB.DrawOtherthings()
'gB.DrawOtherthings()
'gB.DrawOtherthings()
'gB.DrawOtherthings()
'gB.DrawOtherthings()
'gB.DrawOtherthings()
'gB.DrawOtherthings()
End Using
End Using
End Using
Problem was with the brush (textBrush : an array of brush). When I dsipose each item in the array and re initialize, looks like something has happened to them (like they are not brushes anymore. See the error again. It says "Parameter is not valid"). So I just redim the array to 0.
Redim textBrush (0)
This clears previous items. Then I redim the array again initilizes each of them when needed.
Redim textBrush (2)
textBrush (0) = Brushes.Yellow
textBrush (1) = Brushes.Red
textBrush (2) = Brushes.Red
This array is used to change text color when up and down key is pressed.
I saw lot of people had mentioned this error in forums
{Name = Reference to a non-shared member requires an object reference. Size=15.0}
I don't what this name is, but it doesn't effect the programme. It is always like that in any Font.
I'm programming a game in XNA, using VB.NET. I want to create an intro to the game that zooms in/out the whole screen and scaling each image to accomplish this is cumbersome at best. I like to be able to draw a lot of .PNG's (or parts of them) onto a whole image, to then be able to manipulate (scale, turn etc) that whole image, before drawing it with the spriteBatch. The examples I can find use something like:
dim bitmap as New Bitmap
or
dim image as New Image
but these codes highlights the "Bitmap" or "Image" as red, and I cannot use them. I'd be thankful for any help on this issue!
SpriteBatch works with XNA Texture2D objects, whereas Bitmap and Image are System.Drawing types. They do not work together.
You can create a new RenderTarget2D, set it as active using GraphicsDevice.SetRenderTarget() and draw there using a SpriteBatch. You can then draw the stored render target to screen using a SpriteBatch, since render targets are a type of Texture2D.
So I've experimented with Petri Laarne's answer and finally come up with a workable code (most examples online are using C#, and doesn't explain the entire process). Trying to explain it here:
In Public Class Game1:
Private WithEvents graphics As GraphicsDeviceManager
Private WithEvents spriteBatch, spriteBatch2 As SpriteBatch
In Loadcontent:
Public render2 As RenderTarget2D
spriteBatch2 = New SpriteBatch(GraphicsDevice)
spriteBatch = New SpriteBatch(GraphicsDevice)
render2 = New RenderTarget2D(GraphicsDevice, 1024, 768)
In Draw:
spriteBatch2.GraphicsDevice.SetRenderTarget(render2)
GraphicsDevice.Clear(Color.Black)
srcRect = New Rectangle(440, 0, 440, 440) : destRect = New Rectangle(100, 335, 440, 440)
spriteBatch2.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend) : spriteBatch2.Draw(introNEWMirrorDecos, destRect, srcRect, Color.White) : spriteBatch2.End()
destRect = New Rectangle(300, 335, 440, 440)
spriteBatch2.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend) : spriteBatch2.Draw(introNEWMirrorDecos, destRect, srcRect, Color.White) : spriteBatch2.End()
spriteBatch2.GraphicsDevice.SetRenderTarget(Nothing)
GraphicsDevice.Clear(Color.Black)
destRect = New Rectangle(512, 384, 1024, 768) : srcRect = New Rectangle(0, 0, 1024, 768)
spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend) : spriteBatch.Draw(render2, destRect, srcRect, Color.White, PI / 12, New Vector2(512, 384), SpriteEffects.None, 0) : spriteBatch.End()
This is an example code from the actual game that worked like it was intended: drawing 2 things on the alternate rendering image and then drawing them as one single image (in this case being able to rotate it by pi/12).
Any comments on how to do this differently or more efficient is appreciated, and thank's for the initial answer #Petri Laarne
I am creating program with multileyered picturebox, the image of picturebox is update dynamically from bitmap in memory, and i want to clear the selected part on bitmap to transparent color so i can see image of picturebox behind it.
Here is my code
Dim gBmp As Graphics = Graphics.FromImage(GraphLayer(LayerArray))
Dim TileSrcCrop As New Rectangle(nVal(xTile), nVal(yTile), TileSize, TileSize)
Dim TileDrawSize As New Rectangle(nVal(H), nVal(V), TileSize, TileSize)
gBmp.DrawImage(GraphImage(LayerArray), TileDrawSize, TileSrcCrop, GraphicsUnit.Pixel)
PicMap(LayerArray).Image = GraphLayer(LayerArray)
Thanks
What I'm about to say may only be for Windows icons, but IIRC, the top left pixel must be assigned the color that you want to designate as the color for transparency. You'll usually see MS use Magenta (255, 0, 255). This is called a transparency mask. Then, anywhere you want the color to be transparent, you use the color you placed in the top left pixel.
HTH -- and let me know if it's only for icons, but I think it's for Windows bitmap files, too.
I've created a simple test app that will draw a polygon onto an image given the points I provide. I've created a brush that will fill in the polygon how I want to. Now I want to fill in everything BUT the polygon. So, using my brush, I want to draw around the polygon so all that is visible is what's inside the polygon. Does anyone know how I may be able to accomplish this?
Thanks in advance!
I was surprised not to find this answer anywhere but in looking at the documentation for System.Drawing.Region
the answer seemed very simple.
We can Exclude the polygon (which I assume would need to be a GraphicsPath), from an infinite region. Region.XOR should work the same as Exclude in this case:
Region region = new Region();
region.MakeInfinite();
GraphicsPath polygonPath = GetYourPolygon();
region.Exclude(polygonPath);
e.Graphics.FillRegion(Brushes.Black, region);
In my case I just needed to exclude a plain RectangleF but this did the trick, it filled the surrounding area and left the excluded area alone.
I think that System.Drawing.Graphics.Clip is what you want.
Here is a code sample from that link:
Private Sub SetAndFillClip(ByVal e As PaintEventArgs)
' Set the Clip property to a new region.
e.Graphics.Clip = New Region(New Rectangle(10, 10, 100, 200))
' Fill the region.
e.Graphics.FillRegion(Brushes.LightSalmon, e.Graphics.Clip)
' Demonstrate the clip region by drawing a string
' at the outer edge of the region.
e.Graphics.DrawString("Outside of Clip", _
New Font("Arial", 12.0F, FontStyle.Regular), _
Brushes.Black, 0.0F, 0.0F)
End Sub
To fill everything outside of the region, then you would have to determine the extents of the DC that you are drawing to and then fill that rect, after having set Graphics.Clip to a Region created from your points.
So, you code might look something like this:
Private Sub SetAndFillClip(ByVal e As PaintEventArgs)
' Set the Clip property to a new region.
e.Graphics.Clip = GetRegionFromYourPoints()
' Fill the entire client area, clipping to the Clip region
e.Graphics.FillRectangle(Brushes.LightSalmon, GetWindowExtentsFromYourWindow())
End Sub
This link shows how to create a Region from an array of points:
http://www.vb-helper.com/howto_net_control_region.html
Those who didn't find the solution yet, have a look at this. Worked for me, out of the box. Do as follows,
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
var points = new []
{
new PointF(150, 250),
new PointF( 50, 500),
new PointF(250, 400),
new PointF(300, 100),
new PointF(500, 500),
new PointF(500, 50),
};
using (var path = new GraphicsPath())
{
path.AddPolygon(points);
// Uncomment this to invert:
// p.AddRectangle(this.ClientRectangle);
using (var brush = new SolidBrush(Color.Black))
{
e.Graphics.FillPath(brush, path);
}
}
}
this is my first question on here.
I'm trying to build a dial control as a custom user control in VB.NET. I'm using VS2008.
so far I have managed to rotate image using graphics.rotatetransform . however, this rotate everything. Now I have a Bitmap for the dial which should stay stable and another Bitmap for the needle which I need to rotate.
so far i've tried this:
Dim gL As Graphics = Graphics.FromImage(bmpLongNeedle)
gL.TranslateTransform(bmpLongNeedle.Width / 2, bmpLongNeedle.Height * 0.74)
gL.RotateTransform(angleLongNeedle)
gL.TranslateTransform(-bmpLongNeedle.Width / 2, -bmpLongNeedle.Height * 0.74)
gL.DrawImage(bmpLongNeedle, 0, 0)
As I understand it, the image of the needle should be rotated at angle "angleLongNeedle" although i'm placing the rotated image at 0,0. However, the result is that the Needle doesn't get drawn on the control.
any pointers as to where I might be going wrong or something else I should be doing?
Thanks in advance
First of all, why do you allocate the Graphics object from a bitmap that you then proceed to draw onto the graphics? That doesn’t make sense.
Dim gL As Graphics = Graphics.FromImage(bmpLongNeedle)
' … '
gL.DrawImage(bmpLongNeedle, 0, 0)
What you probably want is a graphics context for the whole image. You then apply the transformations to it and finally draw the bmpLongNeedle image.
Secondly, your translations look inversed: in the first step, you need to move the image to the origin (0, 0); then you rotate it, and then move it back. So the transformation should look like this:
gL.TranslateTransform(-bmpLongNeedle.Width * 0.5, -bmpLongNeedle.Height * 0.5)
gL.RotateTransform(angleLongNeedle)
gL.TranslateTransform(bmpLongNeedle.Width * 0.5, bmpLongNeedle.Height * 0.5)
Notice the inversed order of the TranslateTransforms. Also, why did you translate by 0.74 times the height, instead of half?
oh the bitmap for needle has the pivot point at 0.74 * height.
may be I should have posted this before. but this is what i've done.
Public Class Altimeter
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
Dim bmpBezel As New Bitmap("{path}\Altimeter_Background.bmp")
Dim bmpLongNeedle As New Bitmap("{path}\LongNeedle.bmp")
Dim rect2 As New Rectangle(e.ClipRectangle.X, e.ClipRectangle.Y, e.ClipRectangle.Width, e.ClipRectangle.Height)
'make transparent
bmpBezel.MakeTransparent(Color.Yellow)
bmpLongNeedle.MakeTransparent(Color.Yellow)
Dim angleLongNeedle As Single = (Altitude / 50) * 360
'draw bezel
e.Graphics.DrawImage(bmpBezel, rect2)
'rotate long needle
Dim gL As Graphics = Graphics.FromImage(bmpLongNeedle)
gL.TranslateTransform(bmpLongNeedle.Width / 2, bmpLongNeedle.Height * 0.74)
gL.RotateTransform(angleLongNeedle)
gL.TranslateTransform(-bmpLongNeedle.Width / 2, -bmpLongNeedle.Height * 0.74)
gL.DrawImage(bmpLongNeedle, 0, 0)
MyBase.OnPaint(e)
End Sub
i use e.graphics.drawimage to paint the whole image. i don't really understand what you said about having graphics object for all the images and then drawing the needle? do you have any pseudo code?
thanks