Convert WriteableBitmap pixel format to Bgra32 in c# wpf - c#

I have a WriteableBitmap which loads the bitmap image from file(mostly bmp). The bitmap files I am using have different pixel formats such as Indexed8, Bgra32, etc etc. The problem is that my code only works for bgra32 pixel format. So I need help in converting the bitmaps to Bgra32 pixel format in c# wpf.
Thanks

I have found the solution:
if (bmpSource.Format != PixelFormats.Bgra32)
bmpSource = new FormatConvertedBitmap(bmpSource, PixelFormats.Bgra32, null, 0);

Related

Converting 8bpp Indexed Bitmap to 24bpp and back again with the same custom color palette

I'm making a tool that does some graphical editing to some bitmaps. I have some 8bppIndexed bitmaps with an existing color palette that I have to convert to 24bppRgb to allow me to draw on it and edit colors of pixels based on some options the user selected. Bitmap graphic is the original 8bpp .bmp file:
//Get Bitmap from file
Bitmap graphic = new Bitmap(source);
//Get palette and pixel format
ColorPalette pal = graphic.Palette;
PixelFormat pix = graphic.PixelFormat; //Format8bppIndexed
//Create datagraphic in 24bppRgb to allow for editing
PixelFormat datapix = PixelFormat.Format24bppRgb;
Bitmap datagraphic = graphic.Clone(new Rectangle(0, 0, graphic.Width, graphic.Height), datapix);
After drawing and editing Bitmap datagraphic, I'm trying to convert it back to 8bppIndexed with the same color palette as Bitmap graphic. I can do that like this:
//Convert back to graphic pixel format
datagraphic = datagraphic.Clone(new Rectangle(0, 0, datagraphic.Width, datagraphic.Height), pix); //Format8bppIndexed
//Apply color palette
datagraphic.Palette = pal;
However, after cloning datagraphic with the same pixel format as graphic, it creates an entirely new color palette. The colors in datagraphic are then all incorrect after applying ColorPalette pal. They only match by their index number between the two palettes. Is there another way of doing this that preserves the colors?
And yes, the bitmaps need to be 8bppIndexed with the custom palette. I'm trying to avoid the need to go through Photoshop to change the color index of all the end result data graphics with the correct palette.
I should say that I'm still fairly new to C#. I hope I was clear as to what I'm trying to do. I appreciate any help here. Thanks in advance.
Converting an 8-bit image to 24bpp is trivial: you just paint it on a new image of the same dimensions and the preferred pixel format.
public static Bitmap PaintOn24bpp(Image image)
{
Bitmap bp = new Bitmap(image.Width, image.Height, PixelFormat.Format24bppRgb);
using (Graphics gr = Graphics.FromImage(bp))
gr.DrawImage(image, new Rectangle(0, 0, bp.Width, bp.Height));
return bp;
}
This works with any source image no matter its pixel format, though for images containing transparency you may want to preprocess them to fill any transparent areas, because I don't know if painting with transparency taken into account will work if the image you're drawing on doesn't support alpha.
The reverse, to convert a high-colour image to indexed, is a lot trickier, but if you have the palette, it is certainly possible. The main problem in this case is that using Graphics doesn't work, since indexed graphics don't have coloured pixels; they have a coloured palette, and pixels that just reference those colours.
Editing 8-bit data generally boils down to building a byte array containing the image data, and converting that to an image with the palette slapped onto it. The actual conversion is done by making a new 8bpp Bitmap, opening its backing byte array with the LockBits function, and copying your new data into it with Marshal.Copy.
After that, the final missing link is a method to match your image's coloured pixels to their closest palette match, so you can then take the array of resulting matches and bake it into an 8bpp image. This is generally done by calculating the Pythagorean distance (in 3D RGB colour space) of your colour to each of the palette colours, and then taking the index of the colour for which that distance is the smallest.
The whole process, from start to end, is explained in detail in this answer:
A: How to convert a colored image to a image that has only two predefined colors?
This deals with 2 colours, but the method for dealing with 2 or with 256 colours is completely identical, since the end result in both cases was an 8bpp image.
It could be optimised for dealing with 24bpp images directly instead of converting the input to 32bpp, but that's probably not worth the effort, especially since the method posted there works with absolutely any input.

Convert EmguCV image to system drawing bitmap

I am writing a c# program with emgucv library.
I use the imagebox in emgucv to capture image from webcam.
And I want to get the color pixel of the image by using bitmap.Getpixel() by mouse clicking the imagebox.
However,
it contain error The error is..it cannot implicitly convert type 'Emgu.CV.IImage' to 'System.Drawing.Bitmap'
Can anyone give me idea to solve this problem?
Bitmap bitmap = newdetectimageBox.Image; //error
Please use this code
Image<Bgr, Byte> ImageFrame = newdetectimageBox.Image ; //Capture the cam Image
Bitmap BmpInput = ImageFrame.ToBitmap(); //Convert the emgu Image to BitmapImage
Here's how you do it (image data is NOT shared with the bitmap) - see documentation on emgu website about IImage :
Bitmap bitmap = new Bitmap(newdetectimageBox.Image.Bitmap);
The IImage interface contains property Bitmap.
However if you are using the Image class than you should maybe use the ToBitmap method.

initializing a 48bpp bitmap from a file in c#

I write a 48bppRgb to a file but when I create a bitmap from this file it is 32bppArgb(object img2 has a property PixelFormat.32bppArgb).
Minimized example:
Bitmap img1 = new Bitmap(100, 100, PixelFormat.Format48bppRgb);
img1.Save("/img1.bmp");
Bitmap img2 = new Bitmap("/img1.bmp");
Why?
More than one problem. You didn't save the image in the BMP format. The default format for Image.Save(string) is PNG. The PNG encoder built into GDI+ doesn't support 48bpp images. Saving as a BMP requires specifying the image format:
Bitmap img1 = new Bitmap(100, 100, PixelFormat.Format48bppRgb);
img1.Save("c:/temp/img1.bmp", ImageFormat.Bmp);
You'll however find that the BMP encoder doesn't support 48bpp images either, you'll get a 24bpp image when you load it back. None of the codecs supports 48bpp.
There's lots of missing functionality in GDI+. ImageFormat.Icon doesn't work for example, it actually saves a PNG. And support for any of the Indexed pixels formats is quite poor. If you need this kind of support then you'll need a professional imaging library. LeadTools or ImageMagick are the usual choices.

32bit rgb bmp to 24bit rgb bmp in C# problem

I have to convert 32bit rgb bmp images in to 24 bits rgb bmp.
This is what i am trying to do
Bitmap b1=new Bitmap(sorecFileName);
Bitmap b2=new
Bitmap(b1.Size.Width,b1.Size.Height,System.Drawing.Imaging.PixelFormat.Format24bppRgb);
b2.SetResolution(b1.HorizontalResolution, b1.VerticalResolution);
Graphics g=Graphics.FromImage(b2);
g.DrawImage(b1,0,0);
//continue to draw on g here to add text or graphics.
g.Dispose();
b2.Save(destinationFileName);
The code compiles fine and generates the output image of 24bpp but its not in the rgb format any more. Why is this so?
I figured it out as I have a library that takes input of an image as rgb24 and displays it. So when I try to give the file generated by above code as input to the function, it displays noisy image.
However, if I open the same file in paint and save it as 24bpp bmp, and input it to the function, the picture displays fine. What am I missing?
b2.Save(destinationFileName);
You didn't specify the image file format. The default is PNG, not BMP. You now probably have a .bmp file on disk that actually contains a PNG image. That can go undetected for quite a while, lots of graphics programs pay attention to the file header instead of the file name extension. MSPaint for example will have no trouble loading the file. Just like any other program that uses GDI+. You might not be so lucky with a program that blindly assumes that the file contains a BMP and does no checking at all. Fix:
b2.Save(destinationFilename, System.Drawing.Imaging.ImageFormat.Bmp);
if you got a blackimage -
Add g.Clear(Color.White);

C# resize, resave .tif as .jpg gives a blue tint to the new image

I'm building a batch processor to save a directory of .tif images as .jpgs. The processing is working fine. However, the rendered jpgs have a blue-ish tint to them. They aren't "blue", as much as they have a cooler hue, a blue hue. The originals are much brighter and warmer in color. This is how I am creating the resized jpeg:
Bitmap bitmap = new Bitmap(image.Image, size);
Graphics graphics = Graphics.FromImage(bitmap);
graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.None;
graphics.DrawImage(image.Image, 0, 0, size.Width, size.Height);
// Get EncoderInfo("image/jpeg") gets the jpeg Codec by mime type
bitmap.Save(path, GetEncoderInfo("image/jpeg"), EncoderParameters);
The original tif images are 7MB is size - large in comparison to the rendered jpegs. Perhaps that has something to do with it. Not sure.
I've come up empty on the Googles. Does anyone have any experience with this or any advice on what to try next? Thanks!
It could be that the original files have a color profile. In that case, you need to copy that information into the new file as well. I don't know how to do that with .NET's imaging classes.
I would first suggest a test:
Create a plain image with a single colour.
Convert it to jpeg.
Then check in a photo package if the hue has actually changed or if it is your perception.
From the MSDN documentation, it looks like you can be doing this somewhat simpler (assuming image.Image is an actual System.Drawing.Image instance):
image.Image.Save(path, System.Drawing.ImageFormat.Jpeg)
That might help - it looks like you're taking your TIF, converting to a bitmap, and only then converting to a JPG.

Categories