Saving large image to filesystem with emgu CV - c#

I am trying to save a large image (2048 x 2048 pixels) from a C# software to the filesystem using the emgu cv library:
var mat = new Mat( pathToFile, ImreadModes.GrayScale );
mat.Save( "imagename.png" );
The second line of the code snippet throws an exception with the message
System.ArgumentException: Parameter is not valid. at
System.Drawing.Bitmap..ctor(Int32 width, Int32 height, Int32 stride,
PixelFormat format, IntPtr scan0)
I found out, that the size of the image can be a problem, when the save() function creates a bitmap.
What other possibilites do you suggest, to save the Mat-image onto the filesystem?
Note that I the Image is not already stored in the filesystem as my code snippet implies. I am receiving it from a camera.

In fact the problem was not the size of the image. Before saving the image, some strange settings were made to the camera what made all taken pictures unreadable.
Now it works.

Related

Check if GDI+ does not support the pixel format of the file

I'm loading a picture from a file and then create a new Bitmap. Everything works fine but I want to secure more my app.
I'm using Bitmap Constructor (Stream)
public Bitmap(
Stream stream
)
I would like to check if GDI+ does not support the pixel format of the file.
public static Image FromFile(
string filename,
bool useEmbeddedColorManagement
)
Image.FromFile throws OutOfMemoryException if GDI+ does not support the pixel format of the file.
But I would like to avoid using Image.FromFile, because I won't allocate memory etc.
So the question is: how can I check if GDI+ does not support the pixel format of the file.
Thank you!

canon SDk Article by Johannes Bildstein

In Canon SDK sample, how can I take a photo with certain resolution such as 200-300 dpi or change the resolution programmatically, and save the taken photo in another file type, here I need to save in .TIF format? I can't find any function to do it.
author of the article here.
you can change the image resolution by setting the PropID_ImageQuality with one of the ImageQuality enums. Note that not every camera supports every enum value and the actual image resolution depends on the camera and sensor. If you need a pixel-exact image you'll have to resize it yourself.
Also, the image you download from the camera is not modified by the SDK so you can only get the image format that the camera has, usually CR2 and/or Jpg.
To get a tif from a raw file you can use the SDKs image methods. To create a raw image use the EdsCreateImageRef method and to save it use the EdsSaveImage method. As a target you can use EdsTargetImageType.TIFF (or TIFF16 for 16bit per channel).
EDIT:
quick sample for saving an image to tiff (not tested):
IntPtr imgRef;
//Open image
IntPtr inStream;
EDSDK.EdsCreateFileStream("inFile.cr2", EdsFileCreateDisposition.OpenExisting, FileAccess.Read, out inStream);
EDSDK.EdsCreateImageRef(inStream, out imgRef);
EDSDK.EdsRelease(inStream);
//do whatever you like with imgRef now
//Save image
IntPtr outStream;
var settings = new EdsSaveImageSetting();
EDSDK.EdsCreateFileStream("outFile.tif", EdsFileCreateDisposition.CreateAlways, EdsFileAccess.Write, out outStream);
EDSDK.EdsSaveImage(imgRef, EdsTargetImageType.TIFF, settings, outStream);
EDSDK.EdsRelease(outStream);
To get a TIFF image, shoot in RAW format and after downloading the image use the EdsSaveImage function with the EdsTargetImageType set to kEdsTargetImageType_TIFF. The DPI resolution is not relevant directly, but you can always use tools like Exiftool to set the DPI explicitly.

BadImage Error When Loading Tiff CCITTv4 Via SharpDX.Direct2D1.Bitmap.FromWicBitmap

I'm using SharpDX and its accompanying WIC and Direct2D wrappers to do some serverside image manipulation.
The following code works great with JPEG images and is modeled after the SharpDX docs and this Microsoft sample using D2D directly via C++.
However, I get a BadImage error when I try to load a TIFF CCITT (bitonal 1bpp) image. The BadImage error is only thrown at EndDraw, (which happens later on in the commented DrawEndorsement function), or at this line of code which I inserted to make the point at which the issue occurs more obvious:
SharpDX.Direct2D1.Bitmap bitmap = SharpDX.Direct2D1.Bitmap.FromWicBitmap(_renderTarget, _wicBitmap);
The JPEG image I pass in gets to this point and continues with no issues, but the TIFF I pass in gets to this point and causes FromWicBitmap to barf with a BadImage error.
I'm using FormatConverter to convert the TIFF/JPEG pixel formats to an appropriate and supported D2D pixel format, and the converter does change the pixel format GUID for both images, but, again, FromWicBitmap barfs only on the TIFF.
I assumed I was doing something wrong with conversion or misusing SharpDX/D2D, but when I built and ran the aforementioned Microsoft C++ D2D image viewer sample, it loaded and rendered this same TIFF file with no errors. I double checked the sample's code to verify that I was using all the same pixel formats, options, etc, and it looks like I'm doing almost exactly the same thing with SharpDX that the sample is doing with D2D directly.
Clearly Direct2D doesn't like the pixel format of the TIFF image that WIC is handing it, but why didn't the MS sample exhibit the same behavior, and why didn't FormatConverter fix it?
Am I missing something that the D2D sample code is doing?
Am I missing some trick with SharpDX?
Is this a SharpDX bug?
Thanks!
public byte[] BuildImage(byte[] image, Format saveFormat)
{
SharpDX.WIC.Bitmap _wicBitmap;
WicRenderTarget _renderTarget;
BitmapFrameDecode bSource;
FormatConverter converter = new FormatConverter(_factoryManager.WicFactory);
using (MemoryStream systemStream = new MemoryStream(image))
using (WICStream wicStream = new WICStream(_factoryManager.WicFactory, systemStream))
{
BitmapDecoder inDecoder = new BitmapDecoder(_factoryManager.WicFactory, wicStream, DecodeOptions.CacheOnLoad);
if (inDecoder.FrameCount > 0)
{
bSource = inDecoder.GetFrame(0);
converter.Initialize(bSource, SharpDX.WIC.PixelFormat.Format32bppPRGBA, BitmapDitherType.Solid, null, 0.0f, BitmapPaletteType.MedianCut);
_imageWidth = bSource.Size.Width;
_imageHeight = bSource.Size.Height;
}
else
{
throw new Exception("No frames found!");
}
}
_wicBitmap = new SharpDX.WIC.Bitmap(
_factoryManager.WicFactory,
converter,
BitmapCreateCacheOption.CacheOnDemand
);
_renderTarget = new WicRenderTarget(_factoryManager.D2DFactory, _wicBitmap, new RenderTargetProperties());
SharpDX.Direct2D1.Bitmap bitmap = SharpDX.Direct2D1.Bitmap.FromWicBitmap(_renderTarget, _wicBitmap);
//DrawEndorsement(_renderTarget);
_renderTarget.Dispose();
bSource.Dispose();
converter.Dispose();
return SaveImage(saveFormat, _wicBitmap);
}
As xoofx pointed out, turns out that this was caused by my disposing of the WIC/MemoryStreams underlying the FormatConverter while it was still in use.
This was causing JPEGs to be corrupted on write, and weirdly causing the TIFFs to fail even before that.
Extended the using scope accordingly and that fixed it.

Converting WriteableBitmap to Bitmap for use in EmguCV

In my code, I'm receiving WriteableBitmaps from a byte array (in turn from a Kinect) and I'd like to turn them into bitmaps for use with EmguCV. Currently this is the code I have:
// Copy the pixel data from the image to a temporary array
colorFrame.CopyPixelDataTo(this.colorPixels);
// Write the pixel data into our bitmap
this.colorBitmap.WritePixels(
new Int32Rect(0, 0, this.colorBitmap.PixelWidth, this.colorBitmap.PixelHeight),
this.colorPixels,
this.colorBitmap.PixelWidth * colorFrame.BytesPerPixel,
0);
BitmapEncoder encoder = new BmpBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(colorBitmap));
MemoryStream ms = new MemoryStream();
encoder.Save(ms);
Bitmap b=new Bitmap(ms);
Image<Gray, Byte> img = new Image<Gray, Byte>(b);
img = img.ThresholdBinary(new Gray(200), new Gray(255));
I got the bottom half of the code from here.The code compiles and everything, but hangs when I'm trying to run the program (it's supposed to perform some operations on the image and then convert it back to a format that can be presented as an image.) Pausing my code and then using IntelliTrace in VS 2013, I get the following Exception at Image<Gray, Byte> img = new Image<Gray, Byte>(b); "A System.ArgumentException was thrown: URI formats are not supported." Using alternate code, from where I go directly from byte to bitmap gives me the same error. (Code can be found here.)
Anyone got tips on how to resolve this error, or alternate ways of casting to bitmap? I'm a newbie with C# & EmguCV and I'd greatly appreciate it.
Turns out all the code is fine. I'm not too sure on the technical details of the error, but the error is received when trying to write a Gray16 image in the WriteableBitmap (which is to be transformed into a Emgu Image.) Bgr565 or other formats are supported and I believe Gray16 wasn't fully implemented by MS. If doing a WinForms application, Format16bppGray will also give the same error.
I resolved to using a Gray Emgu image while writing the Bitmap as a Bgr555, which is a lot more noisy, but better than nothing.
I had the same issue. The exception with "URI formats are not supported" had nothing to do with the bitmap but with loading needed opencv dlls. I just copied the x86 and x64 folders including opencv_core290.dll and others to my executable directory.

Convert bitmap from 16bpp to 8bpp in C#

I have a Bitmap with 16bpp. I want to convert that image in my ASP.NET side in a 8bpp image.
I tried a lot of options which I found in the internet but nothing works for me.
I also tried that way: C# Converting 32bpp image to 8bpp
But if I want to save the file, I get the following error:
Exception Details: System.Runtime.InteropServices.ExternalException: A generic error occurred in GDI+.
Line 278: System.Drawing.Image img2 = Convert(bm_resize);//byteArrayToImage(gray);
Line 279:
Line 280: img2.Save(helper+"grey2.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
Line 281: }
Line 282:
Is there any correct way for my problem?
Full Code:
System.Drawing.Image img2 = Convert(bm_resize);
img2.Save(path+"test.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
public static System.Drawing.Image Convert(Bitmap oldbmp)
{
using (MemoryStream ms = new MemoryStream())
{
oldbmp.Save(ms, ImageFormat.Gif);
ms.Position = 0;
return System.Drawing.Image.FromStream(ms);
}
}
The problem is caused by disposing the memory stream before the image is saved.
I believe GDI+ requires the memory stream to persist while you are still working with an Image created from the memory stream.
See the Microsoft Support article.
I use a little helper function to create 1 bpp monochrome bitmaps in .NET. Check out this link, it also works great for 8 bpp
http://www.wischik.com/lu/programmer/1bpp.html
hope this could help!
AForge.Net has a good collection of free (under Lesser GPL License) routines for such changes and a lot more. Conversion of 16bpp to 8bpp is as simple as this.

Categories

Resources