ThinkGeo.com    |     Documentation    |     Premium Support

GDI+ error in GdiPlusRasterLayer

Greetings,


I am trying to display some raster data on my map, however with some files I am getting the following exception:


System.InvalidOperationException {"GDI+ threw a status error code."}


 


In my debugging I have found that it only occurs on specific raster files.  I've included one of the files that causes this error as an attachment.  Any help in either fixing this problem, or working around this problem so that my application doesn't crash would be much appreciated.  Thanks in advance.



984-sample.zip (19.5 KB)

Ryan,


Thanks for your post!
 
I tried the data your provided and it works fine. Following is the code for it and its screenshots.

    winformsMap1.MapUnit = GeographyUnit.DecimalDegree;
            winformsMap1.BackgroundOverlay.BackgroundBrush = new GeoSolidBrush(GeoColor.GeographicColors.ShallowOcean);

            GdiPlusRasterLayer worldImageLayer = new GdiPlusRasterLayer(@"C:\Post6073\sample\sample.gif");
            worldImageLayer.UpperThreshold = double.MaxValue;
            worldImageLayer.LowerThreshold = 0;

            LayerOverlay ImageOverlay = new LayerOverlay();
            ImageOverlay.Layers.Add("WorldImageLayer", worldImageLayer);
            winformsMap1.Overlays.Add(ImageOverlay);

           // winformsMap1.CurrentExtent = new RectangleShape(-118.098, 84.3, 118.098, -84.3);
            worldImageLayer.Open();
            winformsMap1.CurrentExtent = worldImageLayer.GetBoundingBox();
            worldImageLayer.Close();

            winformsMap1.Refresh();

ScreenShot:



 
Let me know if any more questions.
 
Thanks
 

Yale



Yale, 
  
 I have created a sample app that demonstrates this issue.  It was too large to upload here so I have e-mailed it to support@thinkgeo.com and asked that they forward it to you. 
  
 Thanks for your help.

 


Ryan,
 
I am sorry to say that the samples from our support still can work correctly. Following is the screenshot:
 

 
I found the current extent is not set correctly before you refresh. Please try the following code in the button click event:

private void button1_Click(object sender, EventArgs e)
        {
            GdiPlusRasterLayer l = new GdiPlusRasterLayer(@".\Data\sample.gif");
            l.LowerThreshold = 0;
            l.UpperThreshold = Double.MaxValue;
            l.Transparency = 150F;
            
            map.Overlays["Sample"].Lock.EnterWriteLock();
            (map.Overlays["Sample"] as LayerOverlay).Layers.Add(l);
            map.Overlays["Sample"].Lock.ExitWriteLock();

            l.Open();
            map.CurrentExtent = l.GetBoundingBox();
            l.Close();

            map.Refresh();
        }

If you still have problems, can you let me know your OS environment? And did you install pervious package before installing the 3.0.362 version?


 
Let me know if you have more questions.
 
Thanks.
 
Yale

Yale,


I am using 3.0.362 on 32-bit XP.  I have had previous versions before 362.  I added your suggested code and still get the exception.  I have included the stacktrace (sorry for not including it before, it completely slipped my mind) in case it helps at all. 


 


Thanks for your time and help,


Ryan


 


System.InvalidOperationException: GDI+ threw a status error code.


   at ThinkGeo.MapSuite.Core.x22c00ac0fef8ee1a.FastFromFile(String filename)

   at ThinkGeo.MapSuite.Core.GdiPlusRasterSource.OpenCore()

   at ThinkGeo.MapSuite.Core.RasterSource.Open()

   at ThinkGeo.MapSuite.Core.RasterLayer.OpenCore()

   at ThinkGeo.MapSuite.Core.Layer.Open()

   at _6073Sample.Form1.button1_Click(Object sender, EventArgs e) in C:\Documents and Settings\Desktop\6073Sample\6073Sample\Form1.cs:line 45

   at System.Windows.Forms.Control.OnClick(EventArgs e)

   at System.Windows.Forms.Button.OnClick(EventArgs e)

   at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)

   at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)

   at System.Windows.Forms.Control.WndProc(Message& m)

   at System.Windows.Forms.ButtonBase.WndProc(Message& m)

   at System.Windows.Forms.Button.WndProc(Message& m)

   at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)

   at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)

   at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

   at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)

   at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)

   at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)

   at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)

   at System.Windows.Forms.Application.Run(Form mainForm)

   at _6073Sample.Program.Main() in C:\Documents and Settings\rdelapp\6073Sample\6073Sample\Program.cs:line 18

   at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)

   at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)

   at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()

   at System.Threading.ThreadHelper.ThreadStart_Context(Object state)

   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)

   at System.Threading.ThreadHelper.ThreadStart()



Ryan,


Thanks for your post and pasting the stack trace, it definitely helps.
 
Now, it was suspicious that some of your system DLLs are corrupt for some reason, please open the attach solution and run the application, hit the button click to see the “gdiplus.dll” in you system was working correctly or not.
 
This test has nothing to do with Map control, it use want to use a Win32 API from OS system which was used in Map Control.
 
Any more questions just let me know.
Thanks.
 
Yale

990-6073Sample.zip (30.4 KB)

I have run your program and verified the exception still occurs.  I re-downloaded the gdiplus.dll from Microsoft (currently running version 5.1.3102.5581) and tested again with the same result.  I tested your program on a second computer with the same result.  I changed the code a little to find that GdipLoadImageFromFile was returning 3 rather than 0.  My research says 3 means Out Of Memory, however several constructors return error code 3 regardless of what the error is.


I'll see what else I can figure out.  If you have any more ideas they would be greatly appreciated.  Thanks for all your time and help.


 


.Ryan.



Ryan,


It seems something wrong with your OS DLLs. What I attempt to do is try to find a way to fix the problem if this case happened.
 
Please try the following code to see if the bitmap can be get correctly in you machine which throwing exceptions.
 

  private void button1_Click(object sender, EventArgs e)
        {
            string fileName = @".\Data\sample.gif";
            IntPtr loadingImage = IntPtr.Zero;

            Bitmap bitmap = FastFromFile(fileName);
            bitmap.Save(@"C:\SeeitCorrect.bmp");
        }

        public static Bitmap FastFromFile(string filename)
        {
            filename = Path.GetFullPath(filename);

            Bitmap result = null;

            if (result == null)
            {
                try
                {
                    IntPtr loadingImage = IntPtr.Zero;

                    // Keep this. Because before GdipLoadImageFromFile, it must new at least one bitmap.
                    Bitmap bitmap = new Bitmap(1, 1);

                    // We are not using ICM at all, fudge that, this should be FAAAAAST!
                    if (GdipLoadImageFromFile(filename, out loadingImage) == 0)
                    {
                        throw new Exception("Error happened");
                    }

                    result = (Bitmap)imageType.InvokeMember("FromGDIplus", BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.InvokeMethod, null, null, new object[] { loadingImage }, CultureInfo.InvariantCulture);
                }
                catch (Exception)
                {
                    result = (Bitmap)Image.FromFile(filename);
                }
            }
            return result;
        }

 
If it works, probably we will try to integrate this into our product to fix the problem you are encountering.
 
Thanks
 
Let me know if any more questions.
 
Yale