..NET 1.1/2.0
I have a need to display high-resolution scrollable images in a .NET
application (Windows Forms). One well known solution is to create a
Panel with AutoScroll set to "true" and then add a PictureBox or
another Panel to it, that is used to display the image.
The above approach works, however, to my surprise, .NET GDI+-based
graphics are not really hi-res friendly.
Consider the following codes examples:
1)
Bitmap b = new Bitmap( 6000, 6000 );
panel2.BackgroundImage = b; // <-- Works OK
2)
Bitmap b = new Bitmap( 14000, 10000 );
panel2.BackgroundImage = b; // <-- "Out of memory" error
The full stack of the error is:
System.OutOfMemoryException: Out of memory.
at System.Drawing.TextureBrush..ctor(Image image, WrapMode
wrapMode)
at System.Windows.Forms.Control.PaintBackground(Paint EventArgs e,
Rectangle rectangle)
at System.Windows.Forms.Control.OnPaintBackground(Pai ntEventArgs
pevent)
at
System.Windows.Forms.Control.PaintWithErrorHandlin g(PaintEventArgs e,
Int16 layer, Boolean disposeEventArgs)
at System.Windows.Forms.Control.WmEraseBkgnd(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ScrollableControl.WndProc(Mes sage& m)
at System.Windows.Forms.ControlNativeWindow.OnMessage (Message& m)
at System.Windows.Forms.ControlNativeWindow.WndProc(M essage& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32
msg, IntPtr wparam, IntPtr lparam)
Internally, the TextureBrush constructor makes a call to
GdipCreateTexture() method in gdiplus.dll, and, apparently, there is
some limit on the image size that the method can handle.
Obviously, I am hitting some limit of GDI+ here, but still need to
find a solution. I want to stay with .NET, if possible and avoid using
any third-party ActiveX controls.
What alternatives can I pursue?
Will going with .NET 3.x and WPF help?
TIA! 11 9608
There are no real solutions to this problem. A 32 bit process has a 2
gigabyte address limit but in reality the usable limits of memory in a .NET
program are somewhat less.
GDI+ is not well suited to dealing with large images and certainly, a 14000
by 10000 full colour image would hit the scales at a little over 534
megabytes.
An image loaded into memory may have far more memory allocated to it than
just the image file size. This is because the image itself might be held in
memory and then the raster image is also held in it's fully expanded state.
If the picture box is double buffered there may even be two full copies of
the image in memory.
--
--
Bob Powell [MVP]
Visual C#, System.Drawing
Ramuseco Limited .NET consulting http://www.ramuseco.com
Find great Windows Forms articles in Windows Forms Tips and Tricks http://www.bobpowell.net/tipstricks.htm
Answer those GDI+ questions with the GDI+ FAQ http://www.bobpowell.net/faqmain.htm
All new articles provide code in C# and VB.NET.
Subscribe to the RSS feeds provided and never miss a new article.
"Usenet User" <no*****@no.waywrote in message
news:a4********************************@4ax.com...
.NET 1.1/2.0
I have a need to display high-resolution scrollable images in a .NET
application (Windows Forms). One well known solution is to create a
Panel with AutoScroll set to "true" and then add a PictureBox or
another Panel to it, that is used to display the image.
The above approach works, however, to my surprise, .NET GDI+-based
graphics are not really hi-res friendly.
Consider the following codes examples:
1)
Bitmap b = new Bitmap( 6000, 6000 );
panel2.BackgroundImage = b; // <-- Works OK
2)
Bitmap b = new Bitmap( 14000, 10000 );
panel2.BackgroundImage = b; // <-- "Out of memory" error
The full stack of the error is:
System.OutOfMemoryException: Out of memory.
at System.Drawing.TextureBrush..ctor(Image image, WrapMode
wrapMode)
at System.Windows.Forms.Control.PaintBackground(Paint EventArgs e,
Rectangle rectangle)
at System.Windows.Forms.Control.OnPaintBackground(Pai ntEventArgs
pevent)
at
System.Windows.Forms.Control.PaintWithErrorHandlin g(PaintEventArgs e,
Int16 layer, Boolean disposeEventArgs)
at System.Windows.Forms.Control.WmEraseBkgnd(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ScrollableControl.WndProc(Mes sage& m)
at System.Windows.Forms.ControlNativeWindow.OnMessage (Message& m)
at System.Windows.Forms.ControlNativeWindow.WndProc(M essage& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32
msg, IntPtr wparam, IntPtr lparam)
Internally, the TextureBrush constructor makes a call to
GdipCreateTexture() method in gdiplus.dll, and, apparently, there is
some limit on the image size that the method can handle.
Obviously, I am hitting some limit of GDI+ here, but still need to
find a solution. I want to stay with .NET, if possible and avoid using
any third-party ActiveX controls.
What alternatives can I pursue?
Will going with .NET 3.x and WPF help?
TIA!
Bob Powell [MVP] wrote:
There are no real solutions to this problem. A 32 bit process has a 2
gigabyte address limit but in reality the usable limits of memory in
a .NET program are somewhat less.
At least, potential solutions such as MapViewOfFile aren't very accessible
from C#.
>
GDI+ is not well suited to dealing with large images and certainly, a
14000 by 10000 full colour image would hit the scales at a little
over 534 megabytes.
An image loaded into memory may have far more memory allocated to it
than just the image file size. This is because the image itself might
be held in memory and then the raster image is also held in it's
fully expanded state. If the picture box is double buffered there may
even be two full copies of the image in memory.
On Apr 24, 6:04 pm, "Ben Voigt [C++ MVP]" <r...@nospam.nospamwrote:
Bob Powell [MVP] wrote:
If the picture box is double buffered there may
even be two full copies of the image in memory.
The picture box is definitely double buffered. I had a similar
problem a while ago, and the solution was to change the container
control from a picture box to a user control.
Details here: http://nomagichere.blogspot.com/2007...-creature.html
Marc
I suppose it is necessary to use Windows 64bits, and forget about 32 bits.
Carlos.
"Bob Powell [MVP]" <bo*@spamkillerbobpowell.netwrote in message
news:BC**********************************@microsof t.com...
There are no real solutions to this problem. A 32 bit process has a 2
gigabyte address limit but in reality the usable limits of memory in a
..NET
program are somewhat less.
GDI+ is not well suited to dealing with large images and certainly, a
14000
by 10000 full colour image would hit the scales at a little over 534
megabytes.
An image loaded into memory may have far more memory allocated to it than
just the image file size. This is because the image itself might be held
in
memory and then the raster image is also held in it's fully expanded
state.
If the picture box is double buffered there may even be two full copies of
the image in memory.
--
--
Bob Powell [MVP]
Visual C#, System.Drawing
Ramuseco Limited .NET consulting http://www.ramuseco.com
Find great Windows Forms articles in Windows Forms Tips and Tricks http://www.bobpowell.net/tipstricks.htm
Answer those GDI+ questions with the GDI+ FAQ http://www.bobpowell.net/faqmain.htm
All new articles provide code in C# and VB.NET.
Subscribe to the RSS feeds provided and never miss a new article.
"Usenet User" <no*****@no.waywrote in message
news:a4********************************@4ax.com...
.NET 1.1/2.0
I have a need to display high-resolution scrollable images in a .NET
application (Windows Forms). One well known solution is to create a
Panel with AutoScroll set to "true" and then add a PictureBox or
another Panel to it, that is used to display the image.
The above approach works, however, to my surprise, .NET GDI+-based
graphics are not really hi-res friendly.
Consider the following codes examples:
1)
Bitmap b = new Bitmap( 6000, 6000 );
panel2.BackgroundImage = b; // <-- Works OK
2)
Bitmap b = new Bitmap( 14000, 10000 );
panel2.BackgroundImage = b; // <-- "Out of memory" error
The full stack of the error is:
System.OutOfMemoryException: Out of memory.
at System.Drawing.TextureBrush..ctor(Image image, WrapMode
wrapMode)
at System.Windows.Forms.Control.PaintBackground(Paint EventArgs e,
Rectangle rectangle)
at System.Windows.Forms.Control.OnPaintBackground(Pai ntEventArgs
pevent)
at
System.Windows.Forms.Control.PaintWithErrorHandlin g(PaintEventArgs e,
Int16 layer, Boolean disposeEventArgs)
at System.Windows.Forms.Control.WmEraseBkgnd(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ScrollableControl.WndProc(Mes sage& m)
at System.Windows.Forms.ControlNativeWindow.OnMessage (Message& m)
at System.Windows.Forms.ControlNativeWindow.WndProc(M essage& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32
msg, IntPtr wparam, IntPtr lparam)
Internally, the TextureBrush constructor makes a call to
GdipCreateTexture() method in gdiplus.dll, and, apparently, there is
some limit on the image size that the method can handle.
Obviously, I am hitting some limit of GDI+ here, but still need to
find a solution. I want to stay with .NET, if possible and avoid using
any third-party ActiveX controls.
What alternatives can I pursue?
Will going with .NET 3.x and WPF help?
TIA!
Couldn't he just copy portions of the bitmap into a picturebox through
an unsafe method with pointers ? I doubt very much he has a
14000x14000 display, so only a small rectangle of the original image
is shown at any time, and copying 4 bytes at a time is really fast.
I've done it for a graphics app, including zoom levels (by factors of
two), and you can't tell the difference with native routines.
(on a side note, if Bob hadn't written his GDI+ FAQ, my app wouldn't
even exist. My eternal thanks to you, Bob !).
Michel
On 24 avr, 19:48, Usenet User <no.s...@no.waywrote:
.NET 1.1/2.0
I have a need to display high-resolution scrollable images in a .NET
application (Windows Forms). One well known solution is to create a
Panel with AutoScroll set to "true" and then add a PictureBox or
another Panel to it, that is used to display the image.
The above approach works, however, to my surprise, .NET GDI+-based
graphics are not really hi-res friendly.
Consider the following codes examples:
1)
Bitmap b = new Bitmap( 6000, 6000 );
panel2.BackgroundImage = b; // <-- Works OK
2)
Bitmap b = new Bitmap( 14000, 10000 );
panel2.BackgroundImage = b; // <-- "Out of memory" error
The full stack of the error is:
System.OutOfMemoryException: Out of memory.
* *at System.Drawing.TextureBrush..ctor(Image image, WrapMode
wrapMode)
* *at System.Windows.Forms.Control.PaintBackground(Paint EventArgs e,
Rectangle rectangle)
* *at System.Windows.Forms.Control.OnPaintBackground(Pai ntEventArgs
pevent)
* *at
System.Windows.Forms.Control.PaintWithErrorHandlin g(PaintEventArgs e,
Int16 layer, Boolean disposeEventArgs)
* *at System.Windows.Forms.Control.WmEraseBkgnd(Message& m)
* *at System.Windows.Forms.Control.WndProc(Message& m)
* *at System.Windows.Forms.ScrollableControl.WndProc(Mes sage& m)
* *at System.Windows.Forms.ControlNativeWindow.OnMessage (Message& m)
* *at System.Windows.Forms.ControlNativeWindow.WndProc(M essage& m)
* *at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32
msg, IntPtr wparam, IntPtr lparam)
Internally, the TextureBrush constructor makes a call to
GdipCreateTexture() method in gdiplus.dll, and, apparently, there is
some limit on the image size that the method can handle.
Obviously, I am hitting some limit of GDI+ here, but still need to
find a solution. I want to stay with .NET, if possible and avoid using
any third-party ActiveX controls.
What alternatives can I pursue?
Will going with .NET 3.x and WPF help?
TIA!
fd******@hotmail.com wrote:
Couldn't he just copy portions of the bitmap into a picturebox through
an unsafe method with pointers ? I doubt very much he has a
14000x14000 display, so only a small rectangle of the original image
is shown at any time, and copying 4 bytes at a time is really fast.
That doesn't help much. You can't keep the whole image in memory, whether
in a Bitmap, PictureBox, or whatever. The math forbids having
32-bpp*14000x14000 (=~2GB) in a 32-bit address space where 2GB is reserved
by the kernel and some more is taken up by code and other data.
You need MapViewOfFile or AWE or something to select certain parts of the
data into your virtual address space. None of these tools are readily
available to .NET.
I've done it for a graphics app, including zoom levels (by factors of
two), and you can't tell the difference with native routines.
(on a side note, if Bob hadn't written his GDI+ FAQ, my app wouldn't
even exist. My eternal thanks to you, Bob !).
Michel
On 24 avr, 19:48, Usenet User <no.s...@no.waywrote:
>.NET 1.1/2.0
I have a need to display high-resolution scrollable images in a .NET application (Windows Forms). One well known solution is to create a Panel with AutoScroll set to "true" and then add a PictureBox or another Panel to it, that is used to display the image.
The above approach works, however, to my surprise, .NET GDI+-based graphics are not really hi-res friendly.
Consider the following codes examples:
1) Bitmap b = new Bitmap( 6000, 6000 ); panel2.BackgroundImage = b; // <-- Works OK
2) Bitmap b = new Bitmap( 14000, 10000 ); panel2.BackgroundImage = b; // <-- "Out of memory" error
The full stack of the error is:
System.OutOfMemoryException: Out of memory. at System.Drawing.TextureBrush..ctor(Image image, WrapMode wrapMode) at System.Windows.Forms.Control.PaintBackground(Paint EventArgs e, Rectangle rectangle) at System.Windows.Forms.Control.OnPaintBackground(Pai ntEventArgs pevent) at System.Windows.Forms.Control.PaintWithErrorHandli ng(PaintEventArgs e, Int16 layer, Boolean disposeEventArgs) at System.Windows.Forms.Control.WmEraseBkgnd(Message& m) at System.Windows.Forms.Control.WndProc(Message& m) at System.Windows.Forms.ScrollableControl.WndProc(Mes sage& m) at System.Windows.Forms.ControlNativeWindow.OnMessage (Message& m) at System.Windows.Forms.ControlNativeWindow.WndProc(M essage& m) at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
Internally, the TextureBrush constructor makes a call to GdipCreateTexture() method in gdiplus.dll, and, apparently, there is some limit on the image size that the method can handle.
Obviously, I am hitting some limit of GDI+ here, but still need to find a solution. I want to stay with .NET, if possible and avoid using any third-party ActiveX controls.
What alternatives can I pursue? Will going with .NET 3.x and WPF help?
TIA!
Usenet User wrote:
I have a need to display high-resolution scrollable images in a .NET
application (Windows Forms).
2)
Bitmap b = new Bitmap( 14000, 10000 );
panel2.BackgroundImage = b; // <-- "Out of memory" error
To work on a 32-bit stack, you've basically got to give up trying to
load the whole bitmap into memory. You're going to have to create a set
of filters that are able to read slices of scanlines out of the image,
possibly with extra processing to integrate zoom info, etc. In essence,
write a viewer for a model, where the model is the data on-disk. The
FileStream class works fine for multi-gigabyte files.
The image stuff in the .NET/Win32 box won't work at that scale, as we're
talking many gigabytes per image when rasterized. The Windows GDI/+
stuff is designed for images for on-screen display and printing, not so
much for totally scalable image manipulation.
If it seems like too much work / beyond your capability set, then you'll
be better off buying. You will probably be better off buying in any
case, as I assume gigapixel imaging isn't one of your business's core
competencies.
-- Barry
-- http://barrkel.blogspot.com/
"Barry Kelly" <ba***********@gmail.comwrote in message
news:p5********************************@4ax.com...
Ben Voigt [C++ MVP] wrote:
>Barry Kelly wrote:
Ben Voigt [C++ MVP] wrote:
[...]
Depending on the image file format, for any given cropped area, each
subsequent scan line of pixels / pixel groups will likely be very
distant in the file, many strides away. IMO a view that builds up a
screen-viewable picture, whether zoomed out (and thus an aggregate of
data) or zoomed in, is best off processing the file in a forward-only
fashion to pick up the data it needs. To get efficient scrolling, a
combination of caching and prediction would probably help.
MapViewOfFile should gracefully degrade to this, but use memory when possible.
MapViewOfFile will only directly help if the image is a raw bitmap and
you're displaying it with a image pixel to screen pixel ratio <= 1, and
even then it'll be limited. Since you'll need to copy each slice of
pixels into a single bitmap for actual on-screen display, you don't save
as much as you could when avoiding a copy by piggybacking the VM/FS
caching subsystem, IMO.
I was under the impression that mapped files do use the same virtual memory
code, just backed by a real file instead of the swapfile.
Ben Voigt [C++ MVP] wrote:
"Barry Kelly" <ba***********@gmail.comwrote in message
news:p5********************************@4ax.com...
>Ben Voigt [C++ MVP] wrote:
>>Barry Kelly wrote: Depending on the image file format, for any given cropped area, each subsequent scan line of pixels / pixel groups will likely be very distant in the file, many strides away. IMO a view that builds up a screen-viewable picture, whether zoomed out (and thus an aggregate of data) or zoomed in, is best off processing the file in a forward-only fashion to pick up the data it needs. To get efficient scrolling, a combination of caching and prediction would probably help.
MapViewOfFile should gracefully degrade to this, but use memory when possible.
MapViewOfFile will only directly help if the image is a raw bitmap and you're displaying it with a image pixel to screen pixel ratio <= 1, and even then it'll be limited. Since you'll need to copy each slice of pixels into a single bitmap for actual on-screen display, you don't save as much as you could when avoiding a copy by piggybacking the VM/FS caching subsystem, IMO.
I was under the impression that mapped files do use the same virtual
memory code, just backed by a real file instead of the swapfile.
That is the only thing making sense.
But the docs only describe "what" not "how".
Arne
Ben Voigt [C++ MVP] wrote:
"Barry Kelly" <ba***********@gmail.comwrote in message
news:p5********************************@4ax.com...
Ben Voigt [C++ MVP] wrote:
MapViewOfFile will only directly help if the image is a raw bitmap and
you're displaying it with a image pixel to screen pixel ratio <= 1, and
even then it'll be limited. Since you'll need to copy each slice of
pixels into a single bitmap for actual on-screen display, you don't save
as much as you could when avoiding a copy by piggybacking the VM/FS
caching subsystem, IMO.
I was under the impression that mapped files do use the same virtual memory
code, just backed by a real file instead of the swapfile.
That's what I meant. Virtual memory, which requires paging in and out on
demand, is very similar to file-system caching, so they are often
implemented by the same OS subsystem.
-- Barry
-- http://barrkel.blogspot.com/
Thank you for the input, everyone!
I managed to find a couple of "purely .NET" controls that do what I
want. One of them is included in DotImage SDKs by Atalasoft
($600-$2500). The other one is part of Imagistik Image Viewer by
Informatik. (The latter is noticeably slower when resizing images or
displaying thumbnails, however.) Both handle my humongous multi-page
TIFFs rather gracefully. Reflector shows that both solutions
ultimately rely on GDI+ and nothing else. The internals in both cases
are rather complex, though.
On Fri, 09 May 2008 11:53:09 +0100, Barry Kelly
<ba***********@gmail.comwrote:
>Usenet User wrote:
>I have a need to display high-resolution scrollable images in a .NET application (Windows Forms).
>2) Bitmap b = new Bitmap( 14000, 10000 ); panel2.BackgroundImage = b; // <-- "Out of memory" error
To work on a 32-bit stack, you've basically got to give up trying to load the whole bitmap into memory. You're going to have to create a set of filters that are able to read slices of scanlines out of the image, possibly with extra processing to integrate zoom info, etc. In essence, write a viewer for a model, where the model is the data on-disk. The FileStream class works fine for multi-gigabyte files.
The image stuff in the .NET/Win32 box won't work at that scale, as we're talking many gigabytes per image when rasterized. The Windows GDI/+ stuff is designed for images for on-screen display and printing, not so much for totally scalable image manipulation.
If it seems like too much work / beyond your capability set, then you'll be better off buying. You will probably be better off buying in any case, as I assume gigapixel imaging isn't one of your business's core competencies.
-- Barry
This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
by: Steven |
last post by:
Hi there,
I have a list of values that I am displaying in a table (Not using a loop)
I want to be able to put a graphic next to the item with the hightest price.
I have all of the prices in...
|
by: Bill |
last post by:
I'm trying to create a form that allows me to modify the contents of
list. When the user clicks on the modify button, it takes them to a
page which displays the quantity of items they purchase, and...
|
by: Joe Doyle |
last post by:
After connecting to the internet, after about 5 pages I
get an error "ACTIVE SERVICE PAGES CANNOT BE DISPLAYED,
SERVER COULD BE DOWN OR DNS ERROR........." and from there
I cannot view any more...
|
by: Bernardo Gomes |
last post by:
Hi all,
I´m having trouble doing the following:
I have a aspx page without any html in it, and, in the Page_Load, I call a component that returns me a XML, that I have to display in the browser. I...
|
by: moumita |
last post by:
I have the folowing code..the logic according to me is correct..but I
dont know...the msg boxes are not displaying anything...am I supposed
to change any settings ???
Public Class Form1
|
by: Michael Levin |
last post by:
I have a very simple page, which shows 3 Quicktime movies in a table. I
think I'm using just standard simple HTML. In Netscape or Safari on a Mac,
they look fine. In Internet Explorer on a PC, the...
|
by: prats |
last post by:
I want to write a GUI application in PYTHON using QT. This application
is supposed to take in Japanese characters. I am using PyQt as the
wrapper for using QT from python. I am able to take input...
|
by: =?Utf-8?B?TWF0dE0=?= |
last post by:
Is there a way to display/render an ASP page inside of an ASPX page with ASP
..Net 2.0? I'm not trying to back into frames but I have an application that
will allow me to customize complex rendered...
|
by: =?Utf-8?B?Sm9obg==?= |
last post by:
Hi all,
I am developing an application in asp.net, Visual C# (background) and
ATL COM Component.
I am using com component in asp.net page code behind (like
default.aspx.cs).
COM component is...
|
by: trint |
last post by:
I am developing a new website for our company with c# dotNet.
There is no problem displaying this website with ie6. Last week
I downloaded ie7 because a friend of mine said he could only see
half...
|
by: DJRhino |
last post by:
Was curious if anyone else was having this same issue or not....
I was just Up/Down graded to windows 11 and now my access combo boxes are not acting right. With win 10 I could start typing...
|
by: isladogs |
last post by:
The next Access Europe meeting will be on Wednesday 4 Oct 2023 starting at 18:00 UK time (6PM UTC+1) and finishing at about 19:15 (7.15PM)
The start time is equivalent to 19:00 (7PM) in Central...
|
by: Aliciasmith |
last post by:
In an age dominated by smartphones, having a mobile app for your business is no longer an option; it's a necessity. Whether you're a startup or an established enterprise, finding the right mobile app...
|
by: NeoPa |
last post by:
Hello everyone.
I find myself stuck trying to find the VBA way to get Access to create a PDF of the currently-selected (and open) object (Form or Report).
I know it can be done by selecting :...
|
by: NeoPa |
last post by:
Introduction
For this article I'll be using a very simple database which has Form (clsForm) & Report (clsReport) classes that simply handle making the calling Form invisible until the Form, or all...
|
by: Teri B |
last post by:
Hi, I have created a sub-form Roles. In my course form the user selects the roles assigned to the course.
0ne-to-many. One course many roles.
Then I created a report based on the Course form and...
|
by: isladogs |
last post by:
The next Access Europe meeting will be on Wednesday 1 Nov 2023 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM)
Please note that the UK and Europe revert to winter time on...
|
by: nia12 |
last post by:
Hi there,
I am very new to Access so apologies if any of this is obvious/not clear.
I am creating a data collection tool for health care employees to complete. It consists of a number of...
|
by: NeoPa |
last post by:
Introduction
For this article I'll be focusing on the Report (clsReport) class. This simply handles making the calling Form invisible until all of the Reports opened by it have been closed, when it...
| |