if I try to create a bitmap bigger than 19000 px I get the error: Parameter is not valid.
How can I workaround this??
System.Drawing.Bitmap myimage= new System.Drawing.Bitmap(20000, 20000);
Keep in mind, that is a LOT of memory you are trying to allocate with that Bitmap.
Refer to http://social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/37684999-62c7-4c41-8167-745a2b486583/
.NET is likely refusing to create an image that uses up that much contiguous memory all at once.
Slightly harder to read, but this reference helps as well:
Each image in the system has the amount of memory defined by this formula:
bit-depth * width * height / 8
This means that an image 40800 pixels by 4050 will require over 660
megabytes of memory.
19000 pixels square, at 32bpp, would require 11552000000 bits (1.37 GB) to store the raster in memory. That's just the raw pixel data; any additional overhead inherent in the System.Drawing.Bitmap would add to that. Going up to 20k pixels square at the same color depth would require 1.5GB just for the raw pixel memory. In a single object, you are using 3/4 of the space reserved for the entire application in a 32-bit environment. A 64-bit environment has looser limits (usually), but you're still using 3/4 of the max size of a single object.
Why do you need such a colossal image size? Viewed at 1280x1024 res on a computer monitor, an image 19000 pixels on a side would be 14 screens wide by 18 screens tall. I can only imagine you're doing high-quality print graphics, in which case a 720dpi image would be a 26" square poster.
Set the PixelFormat when you new a bitmap, like:
new Bitmap(2000, 40000,PixelFormat.Format16bppRgb555)
and with the exact number above, it works for me. This may partly solve the problem.
I suspect you're hitting memory cap issues. However, there are many reasons a bitmap constructor can fail. The main reasons are GDI+ limits in CreateBitmap. System.Drawing.Bitmap, internally, uses the GDI native API when the bitmap is constructed.
That being said, a bitmap of that size is well over a GB of RAM, and it's likely that you're either hitting the scan line size limitation (64KB) or running out of memory.
Got this error when opening a TIF file. The problem was due to not able to open CMYK. Changed colorspace from RGB to CMYK and didn't get an error.
So I used taglib library to get image file size instead.
Code sample:
try
{
var image = new System.Drawing.Bitmap(filePath);
return string.Format("{0}px by {1}px", image.Width, image.Height);
}
catch (Exception)
{
try
{
TagLib.File file = TagLib.File.Create(filePath);
return string.Format("{0}px by {1}px", file.Properties.PhotoWidth, file.Properties.PhotoHeight);
}
catch (Exception)
{
return ("");
}
}
Related
I'm curious to know what is the maximum bitmap width and height independently of each other. I did find that the maximum size is 32768x32768, but is that just referencing a perfect square? Is 32768x32768 = 1,073,741,824 the total amount of pixels I can play with and I can rearrange those pixels among the width and height as long as the total doesn't exceed?
I don't get any error if I do this:
Dim theBitmap as Bitmap = New Bitmap(450, 100000)
Even though I am unable to open the image after I save it (which I don't need to do), I am still able to work with the bitmap BUT I believe there is something not quite right... The final result does not yield the expected result...
The purpose of what I am doing is irrelevant. All I care about is answers to the questions I stated in the first paragraph. If the answer is that I am limited to 32768 for the height, then I'll change my code accordingly. Thanks!
I was able to figure out the answer to my initial questions. You are indeed able to work with any width and height as long as the total dimension stays within the maximum size specification. You may experience problem saving awkward dimensions (1 by 1,000,000), but if you only need to manipulate a bitmap, you can indeed work with such scenarios.
Cheers to everyone that contributed in the comment section!
.bmps size is constrained by the max size of a uint32_t, which is 4GB.
Any dimensions are acceptable as long as the .bmp remains under 4GB.
However, not all bitmaps are created equal. Monochrome bitmaps only need 1 bit per pixel, and also use a slightly smaller color pallet (8 bytes total) so can have a little more than 4x the total number of pixels a 16 color bitmap needs (which uses 4 bits per pixel, and 64 bytes for the color pallet).
This does not take into account compression, as bmps allow for compression for all non monochrome bmps.
PNG and JPEG have no explicit limit on file size, whereas BMP has a limit of 32K by 32K pixels, which I believe is your problem here (some places state that it can also hold 2Gx2G, but I couldn't find anything related to those claims).
I working on windows phone 7 camera app.I need to convert captured stream ,fix it rotation using exif helper and save as jpeg with quality,orientation,output size parameters.I followed exif rotation article to fix rotation. But the core problem is I need to decode the stream to jpeg first and then perform rotation fix as mentioned in order to save picture to media library.
I use following code:
private WriteableBitmap DecodeImage(Stream photo, int angle)
{
WriteableBitmap source = PictureDecoder.DecodeJpeg(photo);
photo.Seek(0, SeekOrigin.Begin);
System.GC.Collect();
UiDispatcher.BeginInvoke(() =>
{
MessageBox.Show(App.LogMemory("after decode"));
});
switch (angle)
{
case 90:
case 270:
return RotateBitmap(source, source.PixelHeight,
source.PixelWidth, angle);
case 180:
return RotateBitmap(source, source.PixelWidth,
source.PixelHeight, angle);
default:
return source;
}
return null;
}
In RotateBitMap method i have the rotation logic as specified in link but it creates a new
WritableBitmap object from source as follows:
WritablBitmap target = new WritableBitmap(soure.width,source.height); //source is the bitmap passed in argument.
The problem is
PictureDecoder.decodejpeg --consumes 30 mb for my camera captured stream
and creation of the new bitmap in rotate stream method is consuming 30 mb more.Resulting in hike of 60 mb application memory.
this is causing application crash due to memory in lower end(256mb) windows phone devices.
Why is decoding jpeg take 30mb and rotation of stream 30mb.(I tried to source and target bitmaps in rotate stream method to null and forced gc but were of no use.Applications hardly get 60mb on devices.How can i cope up with this requirement??
Any ideas..?How to optimize memory consumption in these cases???
Note: I need to take bitmap from rotatestream method as result as I need to use that bitmap to save as jpeg with output size,quality.
When you use JPEG decoding, you usually end up with a photo in it's full size.
In case it was taken with 8MP (roughly 8000000 pixels) camera, the calculation is this:
8000000 * 32bits = 256 000 000 bits for one picture in memory (which is roughly around 30MB)
(let me remind you that the HTC Titan II has a camera of 16MP, so if you used a photo in full size, it would take up roughly around 62MB in memory!!)
Obviously, to create just one WriteableBitmap, you need 30MB. In order to manipulate the photo in some way, you usually can't do it in place. In other words, you need to create a copy, and that's why it duplicates. Windows Phone has a way of preventing such a big memory consumption by automatically lowering the resolution of the loaded picture, but only when you use it with BitmapImage and SetSource method which takes JPEG stream as a parameter.
I wrote about it some time ago in my article How to open and work with large photos on Windows Phone and it's mentioned in the performance considerations for Windows Phone
So, basically, you should cut down the size of the loaded photo (do you need it in full size anyway?) and the BitmapImage class can easily do it for you automatically keeping it under 2000x2000 px which is roughly 15MB (MAX), so you should be fine if you don't want to be bothered with that.
I have a Windows Application project that deals with Image editing (Cropping & Resizing). Unfortunately these image processings consume a lot of Memory and CPU resources (easily reaches 600MB or 50% cpu) and it is all about cropping and resizing just one gif image that weighs 2.5MB (2300*5400px). More than that, due to large resource consumption, the program gets stuck while resizing...
public static Image Resize(Image imgToResize, Size size)
{
Bitmap b = new Bitmap(size.Width, size.Height);
Graphics g = Graphics.FromImage((Image)b);
g.InterpolationMode = InterpolationMode.Default;
g.SmoothingMode = SmoothingMode.HighSpeed;
g.PixelOffsetMode = PixelOffsetMode.Default;
g.DrawImage(imgToResize, 0, 0, size.Width, size.Height);
g.Dispose();
return (Image)b;
}
public static Image Crop(Image img, Point p1, Point p2)
{
Rectangle cropArea = new Rectangle(p1.X, p1.Y, p2.X - p1.X, p2.Y - p1.Y);
return (img as Bitmap).Clone(cropArea, img.PixelFormat);
}
What methods should I use to avoid this?
I've already tried compressing it to memory stream in several formats but it didn't help (even made it worse)
NOTE: I use the standard .NET Drawing libraries: System.Drawing, System.Drawing.Imaging
Your code is creating copies of the image so you should expect unmanaged memory usage to rise when you call these methods. What matters a great deal is what you do with the original. You would be wise to get rid of it so it no longer takes up memory. You have to call its Dispose() method to do so. Waiting for the garbage collector to do it takes too long. The Bitmap class takes very little managed memory but oodles of unmanaged memory.
From an earlier version of this question: http://snippets.dzone.com/posts/show/4336
Also, AForge.net has several resize functions
This is a tricky one, and one I've run into before. You could split the image into x pieces, depending on the size of the file, then save each one to disk to ensure that the memory is clean.
Next, you resize the component images one at a time, each time, ensuring that the component is disposed before proceeding to the next one. Once you're all done, you stitch them back together, and then crop.
A MAJOR PROBLEM with this approach - if you're resizing upward, this approach will put seams in your image, as the interpolation won't have the surrounding pixels to guess at. But I would think that this approach would work well with resizing downward.
HTH.
Another hint again:
For example in resize, like #Hans pointed out, you create a new Bitmap, which one is your bottlenecks.
But, what if you just draw image resized, the same image which was loaded originally (obviously you made a backup file of original image before on the disk).
After crop what if you just draw a portion of a bitmap that user cropped, so user will see only that rectangle. ?
I mean in general, operate over image you already have, and try (as much as it possible) do not initialize new object for it.
Regards.
write Application.DoEvents(); in your functions, at least it wont get stuck
I'm trying to convert a 32bpp screenshot image to an 8bpp (or 4bpp, or 1bpp) format using C#. I've already looked at several stackoverflow answers on similar subjects and most suggest variations using the following code:
public static Bitmap Convert(Bitmap oldbmp)
{
Bitmap newbmp = new Bitmap(oldbmp.Width, oldbmp.Height, PixelFormat.Format8bppIndexed);
Graphics gr = Graphics.FromImage(newbmp);
gr.PageUnit = GraphicsUnit.Pixel;
gr.DrawImageUnscaled(oldbmp, 0, 0);
return newbmp;
}
However, when this executes, I get a the exception: A graphics object cannot be created from an image that has an indexed pixel format. I understand that 8, 4 and 1bpp images have colour table mappings rather than the actual colour pixels themselves (as in 32 or 16bpp images) so I assume I'm missing some conversion step somewhere, but I'm fairly new to C# (coming from a C++ background) and would prefer to be able do this using native C# calls rather than resorting to PInvoking BitBlt and GetDIBits etc. Anybody able to help me solve this? Thanks.
EDIT: I should point out that I need this to be backwardly compatible to .NET framework 2.0
GDI+ in general has very poor support for indexed pixel formats. There is no simple way to convert an image with 65536 or 16 million colors into one that only has 2, 16 or 256. Colors have to be removed from the source image and that is a lossy conversion that can have very poor results. There are multiple algorithms available to accomplish this, none of them are perfect for every kind of image. This is a job for a graphics editor.
There is one trick I found. GDI+ has an image encoder for GIF files. That's a graphics format that has only 256 colors, the encoder must limit the number of colors. It uses a dithering algorithm that's suitable for photos. It does have a knack for generating a grid pattern, you'll be less than thrilled when it does. Use it like this:
public static Image Convert(Bitmap oldbmp) {
using (var ms = new MemoryStream()) {
oldbmp.Save(ms, ImageFormat.Gif);
ms.Position = 0;
return Image.FromStream(ms);
}
}
The returned image has a 8bpp pixel format with the Palette entries calculated by the encoder. You can cast it to Bitmap if necessary. By far the best thing to do is to simply not bother with indexed formats. They date from the stone age of computing back when memory was severely constrained. Or use a professional graphics editor.
AForge library is doing it perfectly using Grayscale.
var bmp8bpp = Grayscale.CommonAlgorithms.BT709.Apply(bmp);
This class is the base class for image grayscaling [...]
The filter accepts 24, 32, 48 and 64 bpp color images and produces 8
(if source is 24 or 32 bpp image) or 16 (if source is 48 or 64 bpp
image) bpp grayscale image.
Negative stride signifies the image is bottom-up (inverted). Just use the absolute of the stride if you dont care. I know that works for 24bpp images, unaware if it works for others.
You can use System.Windows.Media.Imaging in PresentationCore Assembly take a look at here for more information
I am making an imaging application. I need a 16000 x 16000 pixel image. This is not impossible because in PhotoShop I can create this image for print. (56 x 56 inches, in 300dpi)
I am using this code:
Image WorkImage = new Bitmap(16000, 16000);
This generates an "Invalid Parameter" exception, but not when I do 9000 x 9000 Pixels.
MSDN doesn't say anything about the limits in the constructor.
I know that the data in the bitmap object is in memory, because if the array is too big it can throw an "Out Of Memory" exception, but this is not the case. I would prefer manage this data in a file, but I don't know how.
Thanks.
Photoshop does not allocate gigantic images in contiguous portions of memory as you are trying to do. There are some memory limitations I've encountered when creating very large images.
Consider subdividing your images. This has the benefit of better memory management. If you edit one of your subdivided images, you won't have to update the entire image.
As an aside, a 16000 x 16000 at 4 bytes per pixel is roughly a gigabyte! That's huge. Good luck!
Why not generate a bunch of smaller bitmaps? E.g. 16 bitmaps that are 4k x 4k pixels...?
Oh, and although probably not the cause of the exception you got, there are some funny quirks with large objects / the CLR large object heap. This is covered in some other SO topics that you may want to read just for fun since you're playing with large chunks of memory... E.g.: How to get unused memory back from the large object heap LOH from multiple managed apps?
While I agree with Charlie that you're probably better off with several smaller bitmaps, I just ran the code below on my 32 bit Windows with 2 GB RAM, and it took a while to complete, but I received no errors.
var b = new Bitmap(16000, 16000);
Console.WriteLine("size is {0}x{1}", b.Width, b.Height);
Really, dont mind where is the Bitmap Data. I only need in the output a file (TIFF) with the 16000 x 16000 pixels image. I think that i can create a class (How the bitmap class and the image class) but with the data in the file itself, where i can edit the image.
I am thinking to check the TIFF structure and create a class for create and edit those files partially buffered in memory. I dont want create a object that are more big than a few MB.
But i want to know if there is some class with BMP or TIFF File editing capability... really i dont know.
Thanks for your previous Answers. :)