Как отлаживать вводящие в заблуждение исключения GDI OutOfMemory?

У меня есть функция, которая изменяет размер растрового изображения. Это такая "хлеб с маслом" операция, что я просто скопировал ее из другого проекта:

private Bitmap ResizeBitmap(Bitmap orig)
{
    Bitmap resized = new Bitmap(this.Xsize, this.Ysize, PixelFormat.Format16bppGrayScale);
    resized.SetResolution(orig.HorizontalResolution, orig.VerticalResolution);
    using (Graphics g = Graphics.FromImage(resized))
    {
        g.DrawImage(orig, 0, 0, resized.Width, resized.Height);
    }
    return resized;
}

Однако я продолжал получать исключения OutOfMemory на Graphics g = Graphics.FromImage(resized).

Я знаю, что когда речь идет о GDI, исключения OutOfMemory обычно маскируют другие проблемы. Я также очень хорошо понимаю, что изображение, которое я пытаюсь изменить, невелико и что (насколько мне известно) сборщик мусора не должен иметь проблем со сбором экземпляров, когда они покидают текущую область.

Во всяком случае, я немного поиграл с ним, и в настоящее время он выглядит так:

private Bitmap ResizeBitmap(Bitmap orig)
{
    lock(orig)
    {
        using (Bitmap resized = new Bitmap(this.Xsize, this.Ysize, PixelFormat.Format16bppGrayScale))
        {
            resized.SetResolution(orig.HorizontalResolution, orig.VerticalResolution);
            using (Graphics g = Graphics.FromImage(resized))
            {
                g.DrawImage(orig, 0, 0, resized.Width, resized.Height);
            }
            return resized;
        }
    }
}

Но теперь я получаю исключение InvalidOperation на resized.SetResolution(orig.HorizontalResolution, orig.VerticalResolution);

Мне надоело ковыряться в темноте. Есть ли лучший способ справиться с этими надоедливыми операциями GDI?


person Tom Wright    schedule 02.10.2012    source источник
comment
Просто интересно - вы пытаетесь использовать GDI+ в приложении ASP.NET? Мы делали это некоторое время, пока не узнали, что он не поддерживается и будет падать (иногда).   -  person GarethOwen    schedule 02.10.2012
comment
@GarethOwen Нет, это приложение winforms.   -  person Tom Wright    schedule 02.10.2012


Ответы (1)


Из Graphics.FromImage определения метода:

Если изображение имеет формат индексированных пикселей, этот метод выдает исключение с сообщением «Объект Graphics не может быть создан из изображения, имеющего формат индексированных пикселей».

Хотя полученное вами исключение действительно вводит в заблуждение, вы пытаетесь выполнить неподдерживаемую операцию. Похоже, вам нужно изменить размер этого растрового изображения как необработанного блока памяти, а не как растровое изображение GDI+.

person Alex F    schedule 02.10.2012
comment
Просто проверяю - Format16bppGrayScale считается форматом индексированных пикселей? - person Tom Wright; 02.10.2012
comment
Да, все изображения в градациях серого фактически имеют индексированный формат с палитрой градаций серого (0,0,0), (1,1,1) ... Format16bppGrayScale упоминается как неподдерживаемый в разделе Graphics.FromImage MSDN. - person Alex F; 02.10.2012
comment
Спасибо. Это решает насущную проблему, но я оставлю вопрос открытым на некоторое время, так как хотел бы услышать об общих методах отладки. - person Tom Wright; 03.10.2012