We are needing a BlendState to act as the following:
Transparent PNGs are drawn as expected, with anything behind them preserved
We use Color.White to draw a PNG as-is
We will change the alpha channel of the color to change the "opacity" of the texture
To get this effect, BlendState.AlphaBlend is close, but draws white as the transparent part if we set alpha to 100 or any number other than 255.
So we attempted this:
_blendState = new BlendState();
_blendState.AlphaSourceBlend = Blend.SourceAlpha;
_blendState.AlphaDestinationBlend = Blend.InverseSourceAlpha;
_blendState.ColorSourceBlend = Blend.SourceAlpha;
_blendState.ColorDestinationBlend = Blend.InverseSourceAlpha;
This works, except we now get undesired effects if two PNGs are on top of one another. Basically we get some weird lines where it looks like pixel data is being added (or something).
Example:
Effectively, BlendState.AlphaBlend is this:
_blendState = new BlendState();
_blendState.AlphaSourceBlend = Blend.SourceAlpha;
_blendState.AlphaDestinationBlend = Blend.InverseSourceAlpha;
_blendState.ColorSourceBlend = Blend.One;
_blendState.ColorDestinationBlend = Blend.InverseSourceAlpha;
Image looks better than above:
But then alpha doesn't work, using 100 as alpha would replace the background with white.
What BlendState should we use to get our desired effect from SpriteBatch? We are OK to use a different color such as Color.Black there is another way to get it to work.
*PS - another nice feature would be if we could use Color.Red to "tint" a texture, but we want it to work in general first.
Try setting premultipliedAlpha to false for those .png's in your Content Project.
Unfortunately, I don't know how to resolve this issue when using Texture2d.FromStream().
Related
I am using the following code snippet to remove the background from an image.
int[] bgColors = {203,255,240}
ImageMagick.MagickImage image = new ImageMagick.MagickImage("input.jpg")
ImageMagick.MagickImage combineMask= new ImageMagick.MagickImage("mask.jpg")
combineMask.Blur(7, 30);
image.Composite(combineMask, ImageMagick.CompositeOperator.CopyAlpha);
image.Settings.BackgroundColor = new ImageMagick.MagickColor(bgColors[0], bgColors[1], bgColors[2]);
image.Alpha(ImageMagick.AlphaOption.Remove);
It takes the MagickImage image and the MagickImage combineMask and outputs a combined image as linked below.
Original + Mask = Final
Previously, I never needed anything other than a plain white background (which this provides). Now, I would like to be able to set the color of the background. I started by passing a non (255,255,255) set of colors to the settings to image.Settings.BackgroundColor. This did not accomplish anything. I've been trying to investigate the MagickImage library (through their github, they don't really have very complete documentation), but it has remained inscrutable.
How could I get image.Alpha(ImageMagick.AlphaOption.Remove); to replace the removed section with the background color (or a passed color), or otherwise change the color of the background?
Solution
I've figured out a Solution that takes me 90% of the way there.
int[] bgColors = {203,255,240}
ImageMagick.MagickImage image = new ImageMagick.MagickImage("input.jpg")
ImageMagick.MagickImage combineMask= new ImageMagick.MagickImage("mask.jpg")
combineMask.ColorFuzz = new ImageMagick.Percentage(5);
combineMask.Transparent(ImageMagick.MagickColor.FromRgb(255, 255, 255));
combineMask.Opaque(ImageMagick.MagickColor.FromRgb((byte)0, (byte)0, (byte)0),
ImageMagick.MagickColor.FromRgb((byte)bgColors[0], (byte)bgColors[1], (byte)bgColors[2]));
image.Composite(combineMask, ImageMagick.CompositeOperator.Over);
Instead of using the Black/White mask and grabbing alpha channels, I am converting the white part of the mask to transparent, then converting the black part of the mask to the colors contained in the bgColors.
Now, because the formerly white area is now transparent, I cannot blur the image in order to create a smooth transition between mask and picture, which I still need to fix.
My problem is quite simple, but I can't deal with it. I have a yin-yang.jpg file and I'd like to get only round shape (without rest of rectangle, which should be not clickable) and what is more whole white color change to red one and parts with black color should be excluded from an image as well (not clickable).
That image will be background of my form, which I'd like to show at the start of an application.
private void hello_form_Paint(object sender, PaintEventArgs e)
{
Form f = (Form)sender;
f.BackgroundImage = global::TicTacToe.Properties.Resources.ying_yang1;
GraphicsPath formPath = new GraphicsPath();
Rectangle newRectangle = f.ClientRectangle;
e.Graphics.DrawEllipse(System.Drawing.Pens.Black, newRectangle);
newRectangle.Inflate(-5, -5);
formPath.AddEllipse(newRectangle);
f.Region = new Region(formPath);
}
Paint event on my form which I show makes them round, but it's not all things I have to do. How to exclude a black part from a background and how to change white part into red one?
Given what you've described you may find:
http://msdn.microsoft.com/en-us/library/system.drawing.bitmap.maketransparent(v=vs.71).aspx
Bitmap.MakeTransparent() a useful method to explore, it allows you to turn a given colour in your image transparent.
If you use a file with transparent background like a .png or .gif you should be able to only see the round yin-yang shape when you set it as form background.
You can easily edit a .jpg with i.e. GIMP or Photoshop to make the rectangle transparent outside the circle.
edit: is this what you are trying to do?
I have a problem with PorterDuff.Mode.Multiply, it seems that all alpha channels are set as 'black'. Is this as intended? In photoshop / gimp etc the effect leaves transparency where it should be. Darken leaves the transparency alone, but still applies the effect to values with RGB, this is what I want, but with Multiply's effect.
It's just the PorterDuff.Mode.Multiply that causes the black background problem with the overlay.
Bitmap photo = ((BitmapDrawable)ivPhoto.Drawable).Bitmap;
Bitmap overlay = ((BitmapDrawable)overlay.Drawable).Bitmap;
Point ss = getScaledSize(photo.Width, photo.Height, scrSize.X, scrSize.Y);
Bitmap bresult = Bitmap.CreateScaledBitmap(photo, ss.X, ss.Y, true);
Canvas myCanvas = new Canvas(bresult);
Paint myPaintStyle = new Paint(PaintFlags.FilterBitmap);
myPaintStyle.SetXfermode(new PorterDuffXfermode(PorterDuff.Mode.Multiply));
myCanvas.DrawBitmap(
overlay, //img
ivHair.GetX(), ivHair.GetY(), //x,y
myPaintStyle); //style
return bresult;
Help? :)
This is in Mono for Android
Edit: DstIn has the same undesirable effect. (alpha is black)
I had the same problem for an entire day. I was getting crazy .
What worked for me is this line of code:
yourView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
Place it in the class constructor and now the black background should disappear.
I need to create a transparent GeometryModel3D.
Like this:
I tried this code:
var m = new Model3DGroup();
var panelsGeometry = MyMeshGeometry3D;
Brush br = new SolidColorBrush(Colors.Red);
br.Opacity = 0.5;
m.Children.Add(new GeometryModel3D(panelsGeometry, new DiffuseMaterial(br)) { BackMaterial= new DiffuseMaterial(br) });
But as a result I get this:
What am I doing wrong? Thanks.
You could use a transparent image with an ImageBrush, one pixel would be enough but you will need to set TextureCoordinates on the mesh object.
You need to use TextureCoordinates and you wil have to order the sides to be drawn from back to front so they blend correctly. WPF doesn´t do this.
See this article
Make sure your box mesh geometry contains 24 points. If your box contains the minimum number of points (8), then the behind faces won't be rendered.
For example, see here.
You can download the Normals3D.zip and change the brush opacity of the full mesh boxes to get the desired effect.
Im trying to generate a small square 32 by 32 pixels with a 10 by 10 squareish transparent gap in the middle.
This is what I have so far:
private Image CreatePicture(){
// Create a new Bitmap object, 32 x 32 pixels in size
Bitmap canvas = new Bitmap(32,32,System.Drawing.Imaging.PixelFormat.Format16bppRgb555);
for(int i=10;i<21;i++){
for(int p=10;p<21;p++){
canvas.SetPixel(i,p,Color.Lime);
}
}
canvas.MakeTransparent(Color.Lime);
// return the picture
return canvas;
}
Its a it rough and not going to be the final "optimized version" its just a rough demo script. The problem is the returned image does not transparency instead its just a grey box :(.
Any help appreciated.
Michael
UPDATE:
I have updated the script with the PixelFormat set to an Alpha RGB format which it actually accepts without erroring on runtime. Now though if I remove the "canvas.MakeTransparent(Color.Lime);" line it shows a lime box in the middle with it it just shows a grey box the same colour as the grey background; so it seems as if transparency is being recognised just not implimenting the transparency!
private Bitmap CreatePicture(){
// Create a new Bitmap object, 50 x 50 pixels in size
Bitmap canvas = new Bitmap(82,82,System.Drawing.Imaging.PixelFormat.Format32bppArgb);
for(int i=10;i<71;i++){
for(int p=10;p<71;p++){
canvas.SetPixel(i,p,Color.Lime);
}
}
canvas.MakeTransparent(Color.Lime);
// return the picture
return canvas;
}
[...]Format16bppRgb555
Try to use some format with an alpha channel (...Rgba) here. Also, if the output will be an image later, make sure you use an image format like PNG that supports alpha channels.
It depends on how your going to use or display the image. PNG and Gif are the two file formats that support transparency.
For the bitmap setting of transparency, i used:
Graphics.FromImage(bitmap).FillRectangle(Brushes.Transparent, ...) to set the area I wanted as transparent, then I saved the file out as a PNG to get an image with transparency.
I also tried the MakeTransparent method and ran into problems and the Brushes.Transparent was the solution that worked for my situation.
Hope this gives you a direction to look into.
One last note, I create the Bitmap object with width and height only, I don't specify the pixel format or whatever that's called i.e. bitmap = New Bitmap(width, height);
You probably need to change the image format to Format16bppArgb1555.
Right now, you're using Format32bppArgb or Format16bppRgb555, which is 16 bits per pixel with no alpha information. Transparency requires an alpha channel or alpha bit to be present.
My don't you just SetPixel() to Color.Transparent? Instead of Color.Lime then MakeTransparent? And as others have noted; you need a pixel format with an alpha channel.
The MakeTransparent function does work. You have "grey patches" because your TransparencyKey is not correct. You'll find that if you set your TransparencyKey property to whatever color that grey patch is, the grey patches will indeed become transparent when your image is displayed. The default grey patch I got was labeled as "Control" in color, or basically the default Windows Form background color. Change your TransparencyKey to whatever your grey patch is (in my case Control) and your problem will be solved, no saving of files to the Hard Drive neccessary. Cheers mate.