1

**

DUPLICATE SOLVED THE ISSUE

**

I crawled google quite a while now and I found some answers to this but I can not make it work.
I read that there is a memory leak in .NET when loading/replacing bitmaps. The framework is not autom. releasing the memory from the older bitmaps. The GC can not collect the old bitmap due to an "internal?" reference that is not autom. removed by the framework.

Everything works fine, so you really don't have to read all the code.
I just don't understand where to release that annoying pice of memory.

Any help is very welcome. Thank you in advance.

What I do:

imageTif.Source = _imageManager.getBitmapSource();

public BitmapSource getBitmapSource(){
   //Create Bitmap from Tif
   //Create **NEW** BitmapSource using HBitmap
   //returning BitmapSource
}

This is how I create the Bitmap:

    private Bitmap tiffToBitmap()
    {
        FieldValue[] imageHeight = _tif.GetField(TiffTag.IMAGELENGTH);
        int height = imageHeight[0].ToInt();

        FieldValue[] imageWidth = _tif.GetField(TiffTag.IMAGEWIDTH);
        int width = imageWidth[0].ToInt();

        FieldValue[] bitsPerSample = _tif.GetField(TiffTag.BITSPERSAMPLE);
        short bpp = bitsPerSample[0].ToShort();
        if (bpp != 1)
            return null;

        FieldValue[] samplesPerPixel = _tif.GetField(TiffTag.SAMPLESPERPIXEL);
        short spp = samplesPerPixel[0].ToShort();
        if (spp != 1)
            return null;

        FieldValue[] photoMetric = _tif.GetField(TiffTag.PHOTOMETRIC);
        Photometric photo = (Photometric)photoMetric[0].ToInt();
        if (photo != Photometric.MINISBLACK && photo != Photometric.MINISWHITE)
            return null;

        int stride = _tif.ScanlineSize();
        Bitmap result = new Bitmap(width, height, PixelFormat.Format1bppIndexed);

        // update bitmap palette according to Photometric value
        bool minIsWhite = (photo == Photometric.MINISWHITE);
        ColorPalette palette = result.Palette;
        palette.Entries[0] = (minIsWhite ? Color.White : Color.Black);
        palette.Entries[1] = (minIsWhite ? Color.Black : Color.White);
        result.Palette = palette;

        for (int i = 0; i < height; i++)
        {
            Rectangle imgRect = new Rectangle(0, i, width, 1);
            BitmapData imgData = result.LockBits(imgRect, ImageLockMode.WriteOnly, PixelFormat.Format1bppIndexed);

            byte[] buffer = new byte[stride];
            _tif.ReadScanline(buffer, i);

            Marshal.Copy(buffer, 0, imgData.Scan0, buffer.Length);
            result.UnlockBits(imgData);
        }

        return result;
    }

This is how I create the BitmapSource using HBitmap:

private BitmapSource getBitmapSourceFromBitmap(Bitmap bitmap){
            return System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
                bitmap.GetHbitmap(),
                IntPtr.Zero,
                Int32Rect.Empty,
                BitmapSizeOptions.FromEmptyOptions());
        }
Noel Widmer
  • 4,444
  • 9
  • 45
  • 69
  • Hi, GDI/GDI+ needs still needs to dispose all drawing elements manually, I bet your problem lies here. So it's likely that you are missing a .Dispose() on your GDI bitmap. The GC won't do it for you I'm afraid. – Stígandr Sep 12 '14 at 09:47
  • 1
    @Stian Actually, the finalizer on the `Bitmap` will in fact cause the underlying GDI+ resource to be released. Not immediately, but some time after the collection of the `Bitmap`. In fact, the problem is in the way the OP is creating the `BitmapSource` - `GetHbitmap` leaves the resource dangling. Why are you doing that? – Luaan Sep 12 '14 at 09:59
  • @Luuan I need a BitmapSource to pass into Image.Source since a Bitmap can not convert into an ImageSource. If there there is a better solution to get the BitmapSource I would love to use it! – Noel Widmer Sep 12 '14 at 10:26
  • Oh wow, did not refresh page sry. Testing duplicate thread post now... – Noel Widmer Sep 12 '14 at 10:27
  • Duplicate thread solved the issue. Thanks! – Noel Widmer Sep 12 '14 at 10:34

0 Answers0