cureos / aforge

PCL version of AForge.NET Framework, https://code.google.com/p/aforge/
Other
125 stars 96 forks source link

System.ArgumentOutOfRangeException #7

Closed kaki104 closed 10 years ago

kaki104 commented 10 years ago

Hi

An exception of type 'System.ArgumentOutOfRangeException' occurred in Shim.System.Drawing.DLL but was not handled in user code

Additional information: Specified argument was out of the range of valid values.

namespace ImagePixelEnumerator.Helpers
class ImageBuffer

Line 460

// determines mode
Boolean isAdvanced = passes.Length > 0 && passes[0] is TransformPixelAdvancedFunction;

Trace at ImagePixelEnumerator.Helpers.ImageBuffer.TransformPerPixelBase(ImageBuffer target, IList'1 path, Int32 parallelTaskCount, Delegate[] passes) at ImagePixelEnumerator.Helpers.ImageBuffer.TransformPerPixel(List'1 palette, Image& targetImage, IList'1 path, Int32 parallelTaskCount, TransformPixelFunction[] passes) at ImagePixelEnumerator.Helpers.ImageBuffer.TransformImagePerPixel(Image sourceImage, List'1 palette, Image& targetImage, IList'1 path, Int32 parallelTaskCount, TransformPixelFunction[] passes) at System.Drawing.Graphics.DrawImage(Bitmap source, Int32 x, Int32 y, Int32 width, Int32 height) at CrossPlatform.Infrastructure.StoreApp.StoreAppStorageUtility.GetBitmapPart(Bitmap image, Rectangle sourceRect) at CrossPlatform.Infrastructure.StoreApp.StoreAppStorageUtility.ImageProcessDiabloIII(ImageInfoM workImageInfo, Boolean isSizeCheck) at ScreenShotAutoCut.PCL.ViewModels.FolderDetailPageVM.<.ctor>b0(Object s, PropertyChangedEventArgs e) at System.ComponentModel.PropertyChangedEventHandler.Invoke(Object sender, PropertyChangedEventArgs e) at CrossPlatform.Infrastructure.BindableBase.<>cDisplayClass2.b__0(Object para) at System.Threading.WinRTSynchronizationContext.Invoker.InvokeCore()

My source

private Bitmap GetBitmapPart(Bitmap image, Rectangle sourceRect)
{
  Bitmap bmp = new Bitmap(sourceRect.Width, sourceRect.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
  using (var g = Graphics.FromImage(bmp))
  {
     g.DrawImage(image, sourceRect.X, sourceRect.Y, sourceRect.Width, sourceRect.Height);
  }
  return bmp;
}

image parameter picture screenshot049

Please check it Thank you

PS. One file size 910KB, 55 files loaded My app memory using 920MB... this is problem?

Reduced the memory usage of my images. However, there is still an error occurs in the same spot.

anders9ustafsson commented 10 years ago

@kaki104 Thanks for reporting!

Regarding the image size; internally the image will allocate at least width x height x 4 bytes per image when it is initialized as a Bitmap, so that could explain at least some of the memory consumption you are experiencing.

I am about to debug this issue now, I will get back as soon as I know more about what is causing the exception.

Best regards, Anders

anders9ustafsson commented 10 years ago

I have now given this a closer look, and the exception is thrown in the if statement preceding line 460:

// checks the dimensions
if (Width != target.Width || Height != target.Height)
{
  const String message = "Both images have to have the same dimensions.";
  throw new ArgumentOutOfRangeException(message);
}

The exception will be thrown when bmp and image in your code are of different sizes, which I guess is what has happened in this particular case.

The thing is, the classes and methods in Shim.System and Shim.System.Drawing are really not intended to be used in end-applications, they are primarily included in the assemblies to enable the portable AForge.NET (and Accord.NET) assemblies to build. The way Graphics.DrawImage is used in Accord.NET, the source and destination images will always be of the same size, so as long as this method is only called from Accord.NET the ArgumentOutOfRangeException will not occur.

I do not have any plans to make Shim.System.Drawing a full-fledged WPF/WinRT/WP8 replacement of the original System.Drawing assembly, and I strongly recommend against directly using its classes and methods in your end-user applications.

For image preparation, such as extracting a part of the image before further processing with the AForge.NET libraries, you should instead consider using the methods readily available for WriteableBitmap. When the image is sufficiently prepared, only then should you cast the object to System.Drawing.Bitmap.

From the WriteableBitmapEx library, you could for example use the Blit function to copy the requested part of image to bmp like this:

private Bitmap GetBitmapPart(WriteableBitmap image, Rect sourceRect)
{
  var wbm = BitmapFactory.New((int)sourceRect.Width, (int)sourceRect.Height);
  wbm.Blit(new Rect(0.0, 0.0, sourceRect.Width, sourceRect.Height), image, sourceRect, WriteableBitmapExtensions.BlendMode.None);
  return ((Bitmap)wbm).Clone(System.Drawing.Imaging.PixelFormat.Format24bppRgb);
}
kaki104 commented 10 years ago

Taught using the code solved the problem. Thank you