Groups | Blog | Home
all groups > dotnet drawing api > september 2007 >

dotnet drawing api : Problems with the graphics class


Linus
9/27/2007 3:35:57 AM
Hi,

I'm trying to write some scientific software for my job at a
university and I'm having some problems with the graphics class. I've
included the source that I've used to test things.
Source1.tif is a 512x512 greyscale image and source2.tif is a
3072x2304 greyscale image created by an electron microscope. In gfx1
the main problem is that the color fidelity is compromised somehow as
the the color in the original image is FF and in the output image FE
and so on for every pixel. I've tried to just clone the bitmap image
and the result is the same. The other problem is why do I have to use
the pixeloffsetmode.half? Without it 2 pixels on the top and left edge
gets chopped off and to the right and bottom I get and transparent
edge.
In gfx2 I'm trying to copy an bitmap to a larger one but it always
resizes it no matter what I do. Is there a way to get pixel->pixel
copy without any distortions?
Is there a way to save just a part of a bitmap/graphics without
copying it first?
Can anyone recommend any good books covering graphics/bitmaps in the
NET Framework?

Thanks for any help!
Linus

Dim source1 As Bitmap = New Bitmap("K:\source1.tif")
Dim source2 As Bitmap = New Bitmap("K:\source2.tif")
Dim dest1 As Bitmap = New Bitmap(1024, 1024)
Dim dest2 As Bitmap = New Bitmap(10000, 2304)

Dim gfx1 As Graphics = Graphics.FromImage(dest1)
gfx1.SmoothingMode =
System.Drawing.Drawing2D.SmoothingMode.None
gfx1.InterpolationMode =
Drawing2D.InterpolationMode.NearestNeighbor
gfx1.PixelOffsetMode = Drawing2D.PixelOffsetMode.Half
gfx1.CompositingQuality =
Drawing2D.CompositingQuality.AssumeLinear
gfx1.CompositingMode = Drawing2D.CompositingMode.SourceCopy
gfx1.DrawImage(source1, 0, 0, 1024, 1024)

Dim gfx2 As Graphics = Graphics.FromImage(dest2)
gfx2.Clear(Color.White)
gfx2.SmoothingMode =
System.Drawing.Drawing2D.SmoothingMode.None
gfx2.InterpolationMode =
Drawing2D.InterpolationMode.NearestNeighbor
gfx2.PixelOffsetMode = Drawing2D.PixelOffsetMode.Half
gfx2.CompositingQuality =
Drawing2D.CompositingQuality.AssumeLinear
gfx2.CompositingMode = Drawing2D.CompositingMode.SourceCopy
gfx2.PageUnit = GraphicsUnit.Pixel
gfx2.DrawImageUnscaled(source2, 0, 0)
gfx2.DrawImageUnscaledAndClipped(source2, New Rectangle(3024,
0, 10000, 2304))

dest1.Save("k:\dest1.png",
System.Drawing.Imaging.ImageFormat.Png)
dest2.Save("k:\dest2.png",
System.Drawing.Imaging.ImageFormat.Png)
Bob Powell [MVP]
9/29/2007 1:26:24 PM
Whenever you resize an image the Graphics object needs to reposition the
pixels in a given ratio. The values must eventually be converted to intefers
at some time so rounding losses mean that images can move by a pixel or two.
The PixelOffset.Half mode effectively adds a float value of 0.5 to the
calculation such that the integer rounding goes to the nearest value and is
not automatically rounded down.

Your bitmaps are resizing because you're not taking the declared resolutions
of the originals and the default resolution of a new bitmap into account.
When you create a new image you should set the resolution from the old one
or use the DrawImage method that takes specific source and destination
rectangles and uses the "Pixel" graphics unit.


--
--
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.


[quoted text, click to view]
Linus
10/5/2007 12:46:52 PM
On Sep 29, 2:26 pm, "Bob Powell [MVP]" <b...@spamkillerbobpowell.net>
[quoted text, click to view]

So do I understand it correctly that the graphics object being
manipulated is always being manipulated in single/double and not
integers? And if I use PixelOffset it might shift the image too far in
the other direction?
I'm trying to use the DrawImage method using the upperleftcorner copy
with the pixel graphicsunit and it still resizes it. The DrawImage
method is a bit confusing. Are there any resources that describes the
graphics class in more indepth because the MSDN doesn't do it. Or am I
better off using the bitmaps and creating my own methods using
getpixel and setpixel?

Thanks for the help!

Linus
Bob Powell [MVP]
10/7/2007 12:00:00 AM
The graphics class is very complex but at the same time well thought
out. You certainly don't need to invent your own method for such a
simple case and certainly do not mess with getpixel and setpixel unless
you want the slowest graphics possible.

Calculations are al done in single precision floating point. this
enables the transformation pipeline to work correctly. Integers would be
too inaccurate.

The pixel offset mode is only to lock the pixel to a specific part of a
pixel, it won't move the image too far. What's happening is that the
change in size is causing interpolation which is not always good. Try
using the bilinear mode instead of the bicubic.

Finally, for the best control, use the
DrawImage(Image,Rectangle,int,int,int,int,GraphicsUnit) method.

--
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.





[quoted text, click to view]
Linus
10/20/2007 7:24:29 AM
Thanks for taking the time to answer my questions. I still have
problems with the class. When loading(is this a bug?)/stretching a
greyscale or indexed tiff image the values of the pixel gets shifted
with 1 down (for example from $FF to $FE) if I use NearestNeighbor as
the interpolation method. Any other method (bicubic or bilinear...)
mangles the data beyond use for me.
I've used the DrawImage(Image,Rectangle,int,int,int,int,GraphicsUnit)
method with pixel as graphicsunit but it doesn't help.
Going through a lot of different tiff images, I've noticed that
Drawing2D.PixelOffsetMode.Half doesn't always help as sometimes it
leaves a transparent line at the right and bottom edges.
As I said earlier, I'm writing some scientific software and if I can't
count on getting out non-mangled images it's of little use continuing.
The only solution I see is programming my own methods with Setpixel
and Getpixel but these are insanely slow! Are there any other
alternatives? I've looked at the "Victor Image Processing Library" but
it's a bit too expensive for me and what I'm doing.
One more question:
image0.setpixel(0,0,color.green)
if image0.getpixel(0,0)=color.green then
......
endif

Why doesn't this work?
If I use
if image0.getpixel(0,0).toargb=color.green.toargb then
then it works. Why is this? What's the point of having to convert a
structure into an integer to get it working?

Thanks,
Linus


[quoted text, click to view]

AddThis Social Bookmark Button