I am trying to save a GIF with transparency in GDI+, but it seems to reuse the first color in the color table - is this a bug with GDI?
Even if I manually set the colour and resave a gif to a gif, I can't ever get it to output a transparent gif to file:
Bitmap b = new Bitmap("c:\\temp\\source.gif");
Bitmap canvas = new Bitmap(b.Width, b.Height);
Graphics g = Graphics.FromImage(canvas);
g.Clear(Color.Transparent);
// Draw image
g.DrawImage(b, 0, 0);
canvas.MakeTransparent(Color.Black);
canvas.Save("c:\\temp\\output.gif", System.Drawing.Imaging.ImageFormat.Gif);
In the output image black is never set as the transparency colour.
Alternatively is there a way to do this in WPF?
I suggest you take a look at this Image processing Library ImageMagick http://www.imagemagick.org/
Then use this command to convert the saved gif to a gif with transparent background
convert orig.gif -transparent black transp.gif
This might not produce perfect results but worth a try.You might also want to take a look at ImageMagick's .NET Wrapper https://magick.codeplex.com/ ,if you dont want to do this by running a console command.
Related
I've an image ( logo ) and I would like to pass it as an argument and make the background transparent and then save it.
How can I achieve this ?
This what I've tried :
public string SaveImage(Bitmap bmp,string SavePath,string Name)
{
string path = "";
var format = ImageFormat.Jpeg;
using (var m = new MemoryStream())
{
bmp.Save(m, format);
var img = System.Drawing.Image.FromStream(m);
using (var g = Graphics.FromImage(img)) // This is what I've used for making the background transparent
{
g.Clear(System.Drawing.Color.Transparent);
g.Save();
}
var ImgPath = Path.Combine(SavePath, Path.ChangeExtension(Name,"png"));
img.Save(ImgPath);
path = ImgPath;
}
return path;
}
After testing this function I'm getting a black image as an output ( save image )
Some remarks for your code:
You use System.Drawing types wrapping native GDI+ components, not WPF.
You save the Bitmap with JPEG encoder, which does not support transparency. Even if the logo had a transparent background it is removed by the JPEG encoder
Now you reload the saved image and clear the complete content with transparent color (which will not work either as the reloaded JPEG image will have 24-bit RGB pixel format without alpha support so the whole image will be black)
Possible solutions:
Use PNG encoder instead, which supports transparency. If the logo had a transparent background you don't even need anything else.
If the logo was not transparent originally, use the MakeTransparent method instead of Clear. It will replace a single color so it is not able to restore possible anti-aliased alpha blending. It will also convert the pixel format so can be used also on the reloaded JPEG.
To do the same in WPF you can use this library (disclaimer: written by me). You can use the GetReadWriteBitmapData extension method on a WriteableBitmap to access the same MakeTransparent functionality as above along with a sort of other features. But to restore a nicely anti-aliased alpha background you might want to use the TransformColors method instead if you know how to separate the blended colors.
i have this simple code for image creating
Color clr = ColorTranslator.FromHtml("#0000ff");
using (var bm = new Bitmap(100, 100)) {
using (Graphics g = Graphics.FromImage(bm))
g.Clear(clr);
bm.Save("e:\\blue-square.gif", ImageFormat.Gif);
bm.Save("e:\\blue-square.jpg", ImageFormat.Jpeg);
bm.Save("e:\\blue-square.png", ImageFormat.Png);
}
and here is an example
Why colors in png and jpg are different from html #0000ff color?
How to create transparent png with colored element in it with correct color?
update 1
Bitmap.Save(ImageFormat) has default parameters and i've done some research in this direction.
I decided to start with jpg and my goal is clean #0000ff after save.
There is another save method Bitmap.Save(ImageCodecInfo,EncoderParameters)
and nice example about jpeg quality
https://msdn.microsoft.com/en-us/en-en/library/bb882583(v=vs.110).aspx
I've tried 100L but this is not solve my problem - the color is #0000fe instead of #0000ff
It seems i have to set some other parameters in EncoderParameters object.
I read this https://msdn.microsoft.com/en-us/en-en/library/bb882589(v=vs.110).aspx
and this
Unexpected "Bitmap Region is already Locked" exception with GetEncoderParameterList. Any ideas?
jpeg still no success
update 2
I tried png and custom palette with pixel format PixelFormat.Format8bppIndexed
and result was the same: #3000fe
It's an issue of image compression algorithms
I'm actually trying to add some text to an image in C# with
System.Windows.Forms.TextRenderer.DrawText(Graphics, string, Rectangle, Color, TextFormaFlags)
I prepare my image (which is a png) by loading it in memory, with something similar to
Image image = ImageCache.Get(...);
bitmap = new Bitmap(image);
graphic = Graphics.FromImage(bitmap);
I then draw my text with the above command. The problem is that whatever I use for the color, even something like
System.Drawing.Color.FromArgb(0,255,255,255)
the transparency is not drawn. I tried many settings for
graphics.TextRenderingHint
and different combinations of fonts, transparency level, etc. Is there something I don't understand here? Any hint is appreciated.
Thank you.
As mentionned in the comments : if you try to draw transparent text with
System.Windows.Forms.TextRenderer.DrawText
because you look for the advantages brought by GDI in C#, you just can't. Use
System.Drawing.Graphics.DrawString
instead, even if the result for the word-wrapping is slightly inferior with GDI+.
I got some weird issues when resizing an image with transparency in Magick.NET. I am using Q16-AnyCPU.
I am resizing a 100px image to 400px.
MagickImage image = new MagickImage("test.png");
image.Resize(400, 400);
image.Write("test_resized.png");
I have tried many combinations of image.FilterType and image.Interpolate without any good results.
Only when I use image.AdaptiveResize(400, 400);, it looks somewhat better, but not as expected. The final image I want to resize is much bigger and AdaptiveResize is very slow.
When I disable Alpha via image.Alpha(AlphaOption.Off); I looks quice nice, but I want to keep the alpha.
Source image (the white area is transparent):
What I get:
What I want:
I had to set VirtuaPixelMethod, thanks for the hint:
MagickImage image = new MagickImage("test.png");
image.VirtualPixelMethod = VirtualPixelMethod.Transparent;
image.Resize(400, 400);
image.Write("test_resized.png");
I have a png image file with alpha blending of its own. Now I want to load it onto a form in a mobile. I tried so many ways but not work. Is there any solution? Thanks in advance.
This is what I use to load the image from resource:
Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("drawObj.Graph.png");
Bitmap myPNGImg = new Bitmap(stream);
Then create new bitmap with same size of the images Graph.png:
Bitmap myBlankImg = new Bitmap(48,48);
Graphics mynewGraph = Graphics.FromImage(myNew);
mynewGraph.Clear(Color.Transparent);
Draw the PNG bitmap: mynewGraph.DrawImage(myPNGImg, 0, 0);
And then something I read from internet:(
Rectangle rectDest = new Rectangle(50,50, 100, 100);
ImageAttributes imgatt = new ImageAttributes();
imgatt.SetColorKey(Color.Transparent, Color.Transparent);
myGraph.DrawImage(myNew, rectDest, 0, 0, 99, 99,GraphicsUnit.Pixel, imgatt);
It works, but just clear the four corner of the images(somekind of rounded rectangle). There's still some white border around the images left.
Loading images using Bitmap on Compact Framework will lose alpha information. Setting the color key is an alternative way of doing transparency where you sacrifice an exact single color as the transparent color.
To use alpha blending on Compact Framework, you can use the helper classes from OpenNETCF to load the PNG file, keeping the alpha information (see Transparency and alpha blending), then P/Invoke AlphaBlend. It's not pretty, but it's what it takes. Also be warned that you will take a heavy performance hit for using alpha blending. To bake some images dynamically, it's fine, but for generic on screen drawing operations, you might want to use another approach.
The problem is that in the CF, filling with Color.Transparent actually fills with white (see these two blog entries). Project Resistance has a very good example of how to do this blending (actually several of them).