I have a gray-scale TIFF image which windows properties say its Bit-depth is 4 (which is supposed to mean it is 4 BPP), but when I open the image in C# as a bitmap the pixelFormat property says it is Format8bppIndexed (8 BPP), is it the bitmap constructor changing the pixel format or I misunderstood something?
The TIFF format is an container (like ZIP). One TIFF file can contain various frames containing different files / data. An frame can be a bitmap. And each bitmap can have a different pixelFormat. A TIFF file can (or could) have a preview bitmap that has a different pixelFormat.
To get the actual pixelformat of the first frame you could use this :
Stream imageStreamSource = new FileStream("file.tif", FileMode.Open, FileAccess.Read, FileShare.Read);
TiffBitmapDecoder decoder = new TiffBitmapDecoder(imageStreamSource, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
BitmapSource bitmapSource = decoder.Frames[0];
PixelFormat pixelFormat = bitmapSource.Format;
Related
We have a system that provides images in 8-bit grayscale either tiff or jpg formats. However, the component we have to process the images expects image to be in 8-bit jpg format.
When I use .Net to save the tiff images as jpg it convets it to 24-bit image.
Is there a way, hopefully simple and fast, to convert 8-bit grayscale tiff images to equivalent jpg?
I tried and tried just to conclude that I'm sorry: .Net library's Bitmap class DOES NOT save JPEG as 8bpp even when explicitly stated and data is in grayscale.
(note: although stated in some places, JPEG format DOES support 8bpp).
At Convert an image to grayscale you may find code snipet to convert to grayscale any Image.
Using that code, I was able to save a 8bpp grayscale Image instance with '.jpeg' extension, but stating ImageFormat.Gif... that's a cheat...
My findings show as solution an entirely different approach.
The FreeImage library offers powerful APIs, including the feature needed to solve your problem.
It's home page is at http://freeimage.sourceforge.net/faq.html
But, I could not easily compile it in my Win2008 + VS 2010 machine.
One ought to sweat a lot to make it run on modern environments.
Some hints on how to accomplish that are found at http://www.sambeauvois.be/blog/2010/05/freeimage-and-x64-projects-yes-you-can/
Good luck!
Image img = Image.FromFile(filePathOriginal);
Bitmap bmp = ConvertTo8bpp(img);
EncoderParameters parameters = new EncoderParameters();
parameters.Param[0] = new EncoderParameter(Encoder.ColorDepth, 8);
bmp.Save(filePathNew, jpgCodec, parameters);
bmp.Dispose();
img.Dispose();
...
private static Bitmap ConvertTo8bpp(Image img) {
var bmp = new Bitmap(img.Width, img.Height, System.Drawing.Imaging.PixelFormat.Format8bppIndexed);
using (var gr = Graphics.FromImage(bmp))
{
gr.DrawImage(img, new Rectangle(0, 0, img.Width, img.Height));
}
return bmp;
}
I have an file name data.yuv ( It's contain image data in YUV format).
What I need to do to convert the file to jpg or bmp image with C# ?
If I save the yuv file to image. It's show an green image. Thus, I need codes to convert data from yuv to image.
Open that file by using a FileStream and use the constructor of Bitmap to convert the stream to a valid bitmap.
FileStream fs = new FileStream("somefile.yuv", FileMode.Open);
Bitmap bmp = new Bitmap(fs);
Add a 8 bpp PNG to your resources file.
If you try to use it, like:
Bitmap bmp = properties.Resources.My8bppImage;
The bmp PixelFormat will be 32 ARGB ! But it is wrong, it should be 8 bpp indexed.
How to get the correct Bitmap?
You don't have a lot of options here, both the Visual Studio resource editor and the Bitmap class use a PNG decoder that will convert the image to 32bpp. This is meant to be helpful, 32bpp renders nice and quick.
The fallback option is to use the System.Windows.Media.Imaging.PngBitmapDecoder class. You can pass it the BitmapCreateOptions.PreservePixelFormat option and force it to keep the 8bpp format. You can add the png as a resource by renaming it first to, say, a .bin file so it doesn't try to interpret it as an image file but makes it a byte[]. Then code like this will work:
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.IO;
...
Stream stream = new MemoryStream(Properties.Resources.marble8);
PngBitmapDecoder decoder = new PngBitmapDecoder(stream,
BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
BitmapSource bitmapSource = decoder.Frames[0];
Where "marble8" was the test image I used, substitute your own. You'll need to add references to the WindowsBase and PresentationCore assemblies.
Actually the bitmap created has a file size larger than the input bitmap. I opened the bitmap that was created and it looked completely different to what i inputted. why is that ?
I read a bitmap through FileStream and then i write its contents to a bitmap object.Next i write it as a bitmap file onto harddisk. I cant figure out why the output bitmap is larger than the input bitmap. Could someone please help me.
Bitmap.Save (Image.Save) will, by default, save the image as in PNG format.
If you call Save with an ImageFormat value, you should get your bitmap.
b.Save("test.bmp", ImageFormat.Bmp);
When a bitmap file is created there is often padding added to each row to ensure that each row is a multiple of 4 bytes. When you read the bitmap file into a FileStream the padding is also read.
This can mean that the FileStream is larger than expected and when you write it to a bitmap it will display unexpected behaviour since when you write it to a new Bitmap it treats the padding as if it were your image data.
Sorry I did not understand your problem well. But did you try like this?
private System.Drawing.Bitmap readfromFile(string filename)
{
FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read);
byte[] bytes = new byte[fs.Length];
fs.Read(bytes, 0, Convert.ToInt32(fs.Length));
MemoryStream ms = new MemoryStream(bytes);
System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(ms);
return bmp;
}
and saved like this:
System.Drawing.Bitmap bmp = readfromFile("xxxx --- Path");
bmp.Save("test.bmp", ImageFormat.Bmp);
I tried that and it always returns the same image for me.
I'm trying to get information about a PNG file but I've yet to discover a comprehensive site to help me.
These are some of the semi useful code snippets I have:
Bitmap bmp = new Bitmap(pngFileName);
BitmapData bd = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly,PixelFormat.Format48bppRgb);
and
Stream imageStreamSource = new FileStream(pngFileName, FileMode.Open, FileAccess.Read, FileShare.Read);
var decoder = new PngBitmapDecoder(imageStreamSource, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
BitmapSource bitmapSource = decoder.Frames[0];
With these I've been able to to get the image height and width. However I still need to discover the following information:
Is it RLE encoded?
Is it in native video format?
Is it rotated?
Does it use a grayscale palette?
Does it have a transparency?
Is it RGB or BGR?
I'd really appreciate some pointers on how to acheive this or links to good articles dealing with this. We're working with .NET 4.0
I'm not sure if that helps you, but the best I've seen so far, is to walk the image pixel by pixel in a loop and accomplish your different tasks.
See these answers for examples:
Detecting if a PNG image file is a Transparent image?
Detecting grayscale images with .Net