Saving Windows.Media.Drawing with BmpBitmapEncoder black image - how to remove alpha? - c#

I'm using SVG# (http://sharpvectors.codeplex.com/), to batch convert SVG files to other formats. The SVG images being converted are black line drawings with no background. I've little experience with WPF or the System.Windows.Media namespace, so please excuse me if this is a basic question.
I'm using a modified version of the ImageSvgConverter from SVG#, which accepts a System.Windows.Media.Drawing object, which is then converted using a System.Windows.Media encoder (BmpBitmapEncoder, PngBitmapEncoder etc) to export to the desired file format.
When I export using either a TiffBitmapEncoderor, PngBitmapEncoder or GifBitmap the images are generated as expected. The generated images all have transparent backgrounds.
However, when I export using the JpegBitmapEncoder or BmpBitmapEncoder, all images are coming out black. As the tif, png and gif all have transparent backgrounds, I think that the jpg / bmp images are being drawn correctly, however, as alpha isn't supported in these file formats, having a black output makes sense as the transparency would be interpreted as nothing / black.
I think this is as described in these SO posts Strange bmp black output from BitmapSource - any ideas? , Convert Transparent PNG to JPG with Non-Black Background Color and Background Turns Black When Saving Bitmap - C#.
However, I cannot see a way of applying the solutions is these posts to my problem. Can anyone point me in the right direction?
I have tried applying a white SolidColorBrush to the DrawingContext's PushOpacityMask method, however, this makes no difference.
Really appreciate any pointers.
private Stream SaveImageFile(Drawing drawing)
{
// black output
BitmapEncoder bitmapEncoder = new BmpBitmapEncoder();
// works
//bitmapEncoder = new PngBitmapEncoder();
// The image parameters...
Rect drawingBounds = drawing.Bounds;
int pixelWidth = (int)drawingBounds.Width;
int pixelHeight = (int)drawingBounds.Height;
double dpiX = 96;
double dpiY = 96;
// The Visual to use as the source of the RenderTargetBitmap.
DrawingVisual drawingVisual = new DrawingVisual();
DrawingContext drawingContext = drawingVisual.RenderOpen();
// makes to difference - still black
//drawingContext.PushOpacityMask(new SolidColorBrush(System.Windows.Media.Color.FromRgb(255,255,255)));
drawingContext.DrawDrawing(drawing);
drawingContext.Close();
// The BitmapSource that is rendered with a Visual.
RenderTargetBitmap targetBitmap = new RenderTargetBitmap(pixelWidth, pixelHeight, dpiX, dpiY, PixelFormats.Pbgra32);
targetBitmap.Render(drawingVisual);
// Encoding the RenderBitmapTarget as an image file.
bitmapEncoder.Frames.Add(BitmapFrame.Create(targetBitmap));
MemoryStream stream = new MemoryStream();
bitmapEncoder.Save(stream);
stream.Position = 0;
return stream;
}

You could draw a filled "background" rectangle with an appropriate size prior to the actual drawing object.
using (var drawingContext = drawingVisual.RenderOpen())
{
drawingContext.DrawRectangle(Brushes.White, null, new Rect(drawingBounds.Size));
drawingContext.DrawDrawing(drawing);
}

Related

image overlay picture from Camer_net library showing a lot of pink color

I am making an windows form application in which i am overlaying an image during a webcam stream from the laptop.
the overlayed image is showing absurd colours. it is showing alot of pink colour. is there anything i can do to make the overlayed image look properly.
i am using the camera_Net Library to connect to the webcam
suggestions for overlaying an image during during a webcam video shall also be appreciated.
here is my code to draw the image
string filepath = #"E:\office\lux desktop app\Camera_Net-master\Camera_Net-master\Samples\CameraControlTool\water_PNG3290.png";
Bitmap bitmap1 = new Bitmap(filepath);
g.DrawImage(bitmap1, new Rectangle(400 , 0, 250, 600));
here is the look of the image during webcam stream
and here is the orignal image being overlayed
I think the problem is the image itself. It's an .png image, so I it has the possibility of an alpha-value. The white in the back is cropped out but in between the water, the light blue values are pink.
I would first try to use an easier image. Something like this. I think this will work just fine. Then search for some more complex images and try to find the weak-spot and find some alternative options to bring the image in to the cam.
As #Roman R pointed out that g point correctly to an incorrect background,
the problem was indeed with color format, so the solution is to use the correct image pixelformat based on your image.
here is the complete code
Bitmap bmp = new Bitmap(w, h, PixelFormat.Format32bppRgb);
Graphics g = Graphics.FromImage(bmp);
Image newImage;
newImage = Properties.Resources.red_frame_03;
using (Bitmap oldBmp = new Bitmap(newImage))
using (Bitmap newBmp = new Bitmap(oldBmp))
using (Bitmap targetBmp = newBmp.Clone(new Rectangle(0, 0, newBmp.Width, newBmp.Height), PixelFormat.Format16bppArgb1555))
{
g.DrawImage(targetBmp, new Rectangle(100, 0, 350, 350));
}

Saving a Drawn Image as MonoChrome

Hi everyone i have a image that i draw using graphics.drawline
Bitmap Signature = new Bitmap(x, y);
Graphics g;
g = Graphics.FromImage(Signature);
//MessageBox.Show(cord.Length.ToString());
Pen mypen = new Pen(Brushes.Black);
mypen.Width = 2;
mypen.EndCap = System.Drawing.Drawing2D.LineCap.Square;
mypen.StartCap = System.Drawing.Drawing2D.LineCap.Square;
anyways
Signature.Save(filename);
this works great i am trying to make this image monochrome i have tried many different solutions such as this
Save a 32-bit Bitmap as 1-bit .bmp file in C#
also as soon as i reference the imagetype.bmp it turns black any ideal or suggestions on this, i ran the above link like this
Bitmap converted = BitmapTo1Bpp(Signature);
converted.Save(filename);
but the resulting picture is always pure black can someone please help me save this as a monochrome image
After more searching i found that
g = Graphics.FromImage(Signature);
g.Clear(Color.White);
Adding a White Background to the Graphics Drawing Fixed The Problem

Is there a workaround for overlaying transparent images from resources?

Right now I have a form with a PictureBox on the form. I'm using two partially transparent images and trying to put one on top of the other.
sideMenuWide = rounded rectangle with transparent background (.png) [Bottom image]
labelPointer = triangle with transparent background (.png) [Top image]
Here is my approach:
// METHOD #1 //
Image img1 = Image.FromFile(#"C:\sideMenuWide.png");
Image img2 = Image.FromFile(#"C:\labelPointer.png");
picBox.Image = CombineImages(img1, img2);
// METHOD #2 //
Image imgA = RBS.Properties.Resources.sideMenuWide;
Image imgB = RBS.Properties.Resources.labelPointer;
picBox.Image = CombineImages(imgA, imgB);
And the CombineImage function: (I did not write this function, only modified)
public static Bitmap CombineImages(Image imgA, Image imgB)
{
//a holder for the result (By default, use the first image as the main size)
Bitmap result = new Bitmap(imgA.Size.Width, imgA.Size.Height);
//use a graphics object to draw the resized image into the bitmap
using (Graphics graphics = Graphics.FromImage(result))
{
//set the resize quality modes to high quality
graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
//draw the images into the target bitmap
graphics.DrawImage(imgA, 0, 0, imgA.Width, imgA.Height);
graphics.DrawImage(imgB, 100, 70, imgB.Width, imgB.Height);
}
return result;
}
Method #1 DOES work how I want it to, displays imgB perfectly on top of imgA.
Method #2 however shows imgA just fine but imgB is really faint.
Any ideas on how to overcome this? I would like to be able to do this using Resources instead of having to pull from a file.
If the files work when loaded, but the resources don't, then it sounds like the resx build process or the ResourceManager is doing something undesirable. I'd try embedding the files and reading them directly from a stream rather than relying on the ResourceManager to do it for you.
In your Solution Explorer, Add Existing File to add the file to your project. Get properties on the added file and set it to Embedded Resource=. (Don't add it to a resx file)
In your code, you can now get a stream containing the file's data:
Stream instream = Assembly.GetExecutingAssembly().
GetManifestResourceStream("RBS.labelPointer.png"));
(Hint: The compiler generates an obtuse name for the embedded resource, so after adding the files you can add temporary code to call Assembly.GetExecutingAssembly().GetManifestResourceNames() to get a list of them all and find the file you're interested in)
Load your bitmap/image from the stream:
Image img2 = new Bitmap(inStream);

How to make my image transparent?

I know how to make an image control transparent in C#, but is there a way to make the image (the .jpeg file, not the image control) transparent?
Or, is there a way, when I make the image control transparent, to create new image, save it in some path and give it the other image control's content?
The JPEG file cannot be transparent. However, if you save it as a PNG image it will have a transparency channel.
GIFS also support transparency, but only either completely opaque or completely transparent. Nothing in between.
PNG is your best bet here IMO.
You can set the Image-Controls's Opacity-Property to view it with transparence.
But to get an image-file with transparency, you'll have to render it into a new file.
Here's an example how you can do it.
Image image = new Image(); //or however you get this
image.Opacity = 0.5;
RenderTargetBitmap bmp = new RenderTargetBitmap(image.Source.Width, image.Source.Height, 96, 96, PixelFormats.Pbgra32);
bmp.Render(image);
PngBitmapEncoder png = new PngBitmapEncoder();
png.Frames.Add(BitmapFrame.Create(bmp));
using (Stream fs= File.Create("test.png"))
{
png.Save(fs);
}
There is property transparencycolor. That is what you need if you want to display image on control.

Using RenderTargetBitmap to save a portion of the displayed images

I have a simple WPF application where I display one very large image (9000x2875) and on top of it, many small images (64x64).
To do this, I have a Canvas with one Image, then I programatically add the small images as they arrive.
Now I am trying to save portions of the composite image as png files. I thought I would use a RenderTargetBitmap to render the portion of the Canvas that I wanted. My problem is that I cannot find a good way to save the right portion of the image. Here is a my current hack:
private static void SaveImage(Canvas canvas, string file, int x, int y, int width, int height)
{
//changing 0,0 on the canvas so RenderTargetBitmap works as expected.
canvas.RenderTransform = new MatrixTransform(1d, 0d, 0d, 1d, -x, -y);
canvas.UpdateLayout();
RenderTargetBitmap bmp = new RenderTargetBitmap(width, height, 96d, 96d, Pixelformats.Pbgra32);
bmp.Render(canvas);
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bmp));
using(Stream s = File.Create(file))
{
encoder.Save(s);
}
}
The obvious problem with this is that the display will change due to the RenderTransform. It also makes the application slower. I did try to do a RenderTargetBitmap of the entire canvas, but that was much slower than doing this.
So my questions are:
Is there an easier way to save just a portion of the viewed image?
If not, does someone have a suggestion for a better way to go about this? (I already tried a single WriteableBitmap, but that was about as slow as doing the RenderTargetBitmap of the entire canvas.
What you want to use is a CroppedBitmap, which will allow you to save a cropped portion of your image.
// (BitmapSource bmps)
CroppedBitmap crop = new CroppedBitmap(bmps, new Int32Rect(selRect.X, selRect.Y, selRect.Width, selRect.Height));
Edit: Since there seems to be no way to get this to perform the way you want in WPF I would suggest pre-cropping the large image using GDI+ (without displaying it) and loading the region of it you want onto a smaller canvas.

Categories