开发者

Image.SelectActiveFrame memory problem

I'm writing a control to show images.

My problem comes out using Image class on multipage TIFFs.

I use this (I post only relevant code) at the beginning:

Image img;
int pages;
img = Bitmap.FromFile(filename);
pages = img.GetFrameCount(FrameDimension.Page);

then, when the user wants to show a different page:

public override Image GetPage(int page)
{
    if (page < 1 || page > pages) return null;
    try
    {
        #if !TEST
            img.SelectActiveFrame(FrameDimension.Page, page - 1);
            return new Bitmap(img);
        #else
            MemoryStream ms = new MemoryStream();
            img.SelectActiveFrame(FrameDimension.Page, page - 1);
            img.Save(ms, ImageFormat.Jpeg);
            Image ret = Image.FromStream(ms);
            ms.Flush();
            ms.Dispose();
            return ret;
        #endif
    }
    catch (Exception ex)
    {
        "Tiff GetPage error: {0}".ToDebug(ex.Message);
        return null;
    }
}

Using img.SelectActiveFrame(FrameDimension.Page, page - 1); (in both versions) about 7MB are allocated in memory and those are never freed (even exiting the method)!!!

If I goes to next page 7MB are allocated and not freed everytime, while going back (on an already visited pages) previously allocated memory is u开发者_高级运维sed.

To give you an example: think Task Manager reports my app is using x MB; going one page forward memory increases to x + y (after SelectActiveFrame()) + z (Image ret = ...). Well, I should have x + z (y part should be zero or GC collected exiting the method), but obviously that's not what happens, even calling GC.Collect manually.

Going back to a previously visited page, memory increases effectively only with z, as expected.

I find it terrible (think about a file with 80 pages...), but how can I force img object to free allocated memory? Am I doing something wrong?

I've already thought closing and reopening img, but speed is not good.

Thanks to everybody


Don't use new Bitmap(img) because it will force the system to create new memory for a new Bitmap object using 32-bit color by default.

You can just use var bitmap = (Bitmap)img; to retrieve a Bitmap object for that page.


If I'm not mistaken you're not destroying the used controls at every possible point. I think you might need to test this - but make sure that you're disposing all the used controls.

ie. ImageControlUsed.Dispose();


I answer my question after trying different solutions and accept soluzion given by user965487 because at the end he was right (thanks to Hans Passant too).
If you have a class (call it QV) similar to this

public class QV
{
    Image img;
    int pages;

    public QV(filename) {
       img = Bitmap.FromFile(filename);
       pages = img.GetFrameCount(FrameDimension.Page);
    }

    ~QV() {
        img.Dispose();
        img = null;
    }

    public Image GetPage(int page) {
        if (page < 1 || page > pages) return null;
        img.SelectActiveFrame(FrameDimension.Page, page - 1);
        return new Bitmap(img);
    }
}

then every time you call GetPage(...) your memory will grow not only for the size of returned image, but also for img.SelectActiveFrame(...) statement. I don't know why and how, but it happens. Releasing returned image and calling frees memory for image size, not for the amount taken from SelectActiveFrame() (anyway this memory is not duplicated if you return on a previously seend page).
So you'd better open and close the image everytime, like this:

public class QV
{
    Image img;
    int pages;

    public QV(filename) {
       img = Bitmap.FromFile(filename);
       pages = img.GetFrameCount(FrameDimension.Page);
       img.Dispose();
    }

    public Image GetPage(int page) {
        if (page < 1 || page > pages) return null;
        img = Bitmap.FromFile(filename);
        img.SelectActiveFrame(FrameDimension.Page, page - 1);
        Image ret = Bitmap(img);
        img.Dispose();
        return ret;
    }
}

Payload for opening and disposing image everytime user requests a new page is really nothing compared to dangerous memory allcation done with first solution.
I hope someone needs this.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜