I find when I use the Bitmap.Save method with format ImageFormat.Bmp that the bitmap header info in the file has zero in the biSizeImage field.
From what I can see this is ok according to the specs, but unfortunately the crappy embedded device I am forced to work with insists on it being set correctly.
So the question is how to go about getting this header info field always set when the bitmap is saved?
The issue, as you suspect, is that 0 is a perfectly allowable value for the image size field of an RGB bitmap. The MSDN documentation for the BITMAPINFOHEADER structure confirms this fact:
biSizeImage
The size, in bytes, of the image. This may be set to zero for BI_RGB bitmaps.
If biCompression is BI_JPEG or BI_PNG, biSizeImage indicates the size of the JPEG or PNG image buffer, respectively.
So the implementation in the .NET Framework is simply doing things the standard, documented way. Since you need something else, you'll have to handle the save to file process yourself, which will allow you to manually modify the biSizeImage member of the BITMAPINFOHEADER structure.
A pretty comprehensive example is available here: Saving a Control Image to a Bitmap File. Of course, it's written for the Compact Framework, but most of the individual components are still applicable. You'll need to P/Invoke several functions from the Windows API (visit www.pinvoke.net for the definitions), and work with a DC.
Taking the drawing into your own hands will probably also be faster, because you're using the GDI subsystem, rather than GDI+. An article on that general approach is available here: 1bpp in C#, and it appears to demonstrate taking matters into your own hands with the BITMAPINFOHEADER struct as well.
If you understand unmanaged C++ code, there's a tutorial available here that might give you some idea of what you'd have to implement in C# to do the same thing: Loading and Saving Bitmaps. As you can see, the code required really isn't that long, albeit still more than the one line Bitmap.Save method.
I encountered with this problem too and it solved with a simple trick.
save the bitmap, then open it as a file stream and change the biSizeimage field manually.
picbpp.Save("pic.bmp", ImageFormat.Bmp);
string path = "pic.bmp";
FileStream fs = File.Open(path, FileMode.Open, FileAccess.Write, FileShare.None);
// Change biSizeimage field manually.
Byte[] info = new byte[] {0x10,0x59};
fs.Seek(34, SeekOrigin.Begin);
fs.Write(info, 0, info.Length);
fs.Close();
Related
I was asking myself, why the size of my original tiff is increasing (from 992KB to 9,42 MB), when i save it with Bitmap.Save(). The question came up, because i currently work with tiffs, modifiy them and so on.
I saw two differencen between the files (besides the file size).
The compression.
The originalTiff has no compression displayed in its details.
The savedTiff has LZW compression.
The photometric interpretation. The originalTiffs photometric interpretation is YCbCR. The savedTiffs is RGB.
Is one of these properties the cause of the tenfold size increase?
This is the code i use:
Bitmap bmp = new Bitmap(#"C:\Users\PJ.ITAMS\Deskto\originalTiff.tif");
bmp.Save(#"C:\Users\PJ.ITAMS\Desktop\savedTiff.tif",ImageFormat.Tiff);
bmp.Dispose();
If anything is unclear or i gave too little information i'm sorry and give you everything you ask for!
Thanks in advance.
The file size is larger Because you didn't specify a compression.
This way the file is saved as an uncompressed tif.
The save Function of the Bitmap class is also overloaded with a function that takes EncoderParameters as an argument. This is how you control compression.
you can find more information here:
MSDN documentation of Image.Save (The Bitmap Class implements Image)
Currently, we are determining the size, and whether or not an image contains color by converting it to a Bitmap and the checking the height/width, and checking the PixelFormat for type System.Drawing.Imaging.PixelFormat.Format1bppIndexed to detect color.
What I've noticed though, stepping through the code, it can take 3-5 seconds just to initialize this Bitmap (at least for a very high-resolution TIF image):
ms = new MemoryStream(fileBytes);
bitmap = new System.Drawing.Bitmap(ms);
Is there a faster way to check these two things, straight from the byte array, so I can avoid the slowness of the Bitmap class or is this just what to expect with large TIF images?
This wasn't quite the answer I was hoping for, so I'll leave it open still, but I do want to at least mention one possible "answer". My original problem was that loading up the Bitmap was slow.
I stumbled upon this MSDN article, which explains how Image.FromStream() has an overload that allows you to tell it not to validate the image data. By default, that is set to true. By using this new overload, and setting validateImageData to false - this speeds things up tremendously.
So for example:
using (FileStream fs = new FileStream(this.fileInfo.FullName, FileMode.Open, FileAccess.ReadWrite))
{
using (Image photo = Image.FromStream(fs, true, false))
{
// do stuff
}
}
The author of the article, found that his code ran 93x faster (!).
I'm using the following code to Decode Jpge image
UnmanagedMemoryStream^ mStream = gcnew UnmanagedMemoryStream(_jpegDataBuff, _buffLength);
JpegBitmapDecoder^ decoder = gcnew JpegBitmapDecoder(mStream, BitmapCreateOptions::PreservePixelFormat, BitmapCacheOption::OnLoad);
BitmapSource^ bitmapSource = decoder->Frames[0];
I use the bitmapSource to display on control of WPF, but sometimes the the result as below
I have searched very much on internet, but I did not solve it yet!
Someone can help me?
Many Thanks,
T&T
From the looks of it I would say that either JPEG source is incomplete or invalid. The only exceptions JpegBitmapDecoder throws are ArgumentNullException (stream is null) and FileFormatException. The file format is most probably detected by analyzing file header. The JIF/JFIF file structure holds image description information in a relatively small header followed by a "raw" data.
I guess that decoder is built resilient to ignore invalid (rendered last before gray) and/or missing (rendered gray) blocks. I think the only way to detect is to either analyze final image (maybe checking that last 8x8px block doesn't have same color?) or source (maybe counting data blocks?).
I'm new with Imageresizer from imageresizing.net and i can't figure out how to get the resized image. I need the resized image because i need to add a watermark to it. I need the bitmap of the resized image.
Code:
string fileName = Path.Combine(Server.MapPath("~/Content/Gags"), System.Guid.NewGuid().ToString());
var ResizedImage = ImageBuilder.Current.Build(new ImageJob(UploadGagModel.file, fileName, new Instructions("maxwidth=556&maxheight=1500"), false, true));
I'm using ASP.NET MVC 4 C#
Thanks in advance, if i wasn't clear enough then please tell me!
Avoid using System.Drawing directly at all costs - it is fraught with memory leaks, concurrency issues, and encoding bugs. ImageResizer handles and avoids these for you, and offers a Watermarking plugin as well as SampleOverlay sample plugins to show you how to safely create your own if Watermark can't support your needs.
If, despite my warning, you want to get a Bitmap result, you can pass typeof(Bitmap) as the 'destination' parameter to ImageJob, and access the Bitmap instance from the .Result property.
Other consequences:
The Bitmap instance will not be disposed reliably unless you dispose it within a finally(){} block (use a temporary variable to cross the scope boundary).
ImageResizer will not help you with encoding the result. If you call .Save(), you will get gigantic jpeg files, and no 8-bit PNG or animated gif support.
You will not be able to take advantage of any other pipelines (WIC, FreeImage, etc). Most of our future development will be on better pipelines than GDI+/System.Drawing.
there a way to determine that I am passing the right byte array to the MemoryStream if I want to create an Image out of byte array.
MemoryStream mStream = new MemoryStream();
mStream.Write(byteArray, 0, byteArray.Lenth);
Image imgObj = Image.FromStream(mStream);
How can I, if possible Correct the byteArray that it is a valid byteArray for an Image?
This is a really ominous question, surely you must know where you are reading your data from? When you create an image using Image.FromStream, an ArgumentException will be thrown if it cannot recognise the format. Why don't you use that mechanism for identifying an incorrect stream of data, rather than re-invent the wheel?
I've done a bit of programatic image manipulation myself. The thing you'll want to do is find the spec for the image format that you are modifying and make sure you do everythign you should. For example png files are chunked and have checksums on each section so if you change something in that chunk you have to recalculate the checksum at the end of the section.
After reading your questions and your comments, i think what you're trying is to manipulate the image by manipulating the byte array before you put it into the Image class. And now you claim that your byte array is corrupt for this image format and how you can correct it.
So the answer to this question would be: You corrupted it, you'll fix it.
But to really solve your problem, if your goal is to manipulate the picture itself, just load it into an interims Image and use the Graphics class to manipulate your picture. Afterwards put the result into the real image object you like. Ready, without any hassle about working on the byte array.
here's the answer Image Processing for Dummies with C# and GDI+
OT: i don't know how to put links on comments so I put it in the answers.