Недостаточно памяти для картинки при использовании графики, C # - PullRequest
0 голосов
/ 13 декабря 2018

Код очень прост: я нажимаю кнопку, картинка загружается в PictureBox.

    private void button1_Click(object sender, EventArgs e)
{
        using (FileStream stream = File.OpenRead(FullName))
        {
            pictureBox1.Image = (Bitmap)Bitmap.FromStream(stream).Clone();
            stream.Close();
            stream.Dispose();
        }
}

Но когда из другой функции \ события я использую Graphics на PictureBox'e, он клянется, что тамнедостаточно памяти на Graphics.FromImage.Неважно, что я делаю с этим графиком.Пример:

    using (Graphics g = Graphics.FromImage(pictureBox1.Image))
{
    g.Clear(Color.FromArgb(0, 255, 255, 255));
    pictureBox1.Invalidate();
}

Вопрос в том, почему я могу делать с графикой все, что хочу, перед загрузкой изображения в PictureBox: вырезать, заполнить, нарисовать;но после загрузки картинки я не могу?ps картинка пробовала разных размеров.Та же картинка работает до загрузки (она уже была в стандартном pictureBox) и не работает после загрузки в pictureBox.Прошел довольно много форумов на эту тему, но мой случай (или самый похожий случай) не найден.

Ответы [ 2 ]

0 голосов
/ 13 декабря 2018

Итак, проблема в потоке, используемом Graphics.FromImage. Документация говорит, что поток, открытый из Graphics.FromImage, должен оставаться открытым в течение всей работы с изображением.Хорошо, мы можем использовать MemoryStream:

    MemoryStream ms;

private void button1_Click(object sender, EventArgs e)
{

    ms = new MemoryStream();
    using (FileStream stream = File.OpenRead(FullName))
    {
        stream.CopyTo(ms);
        pictureBox1.Image = Bitmap.FromStream(ms);
    }
}        


private void button2_Click(object sender, EventArgs e)
{
    using (Graphics g = Graphics.FromImage(pictureBox1.Image))
    {
        g.Clear(Color.FromArgb(0, 255, 255, 255));
    }     
}

И image.Clone () нужно удалить, потому что поток должен иметь ссылку на одно и то же изображение, а не на их копии для корректной работы.(Если честно, эта простая программа может работать без MemoryStream)

0 голосов
/ 13 декабря 2018

У вас есть 3 варианта:

1) Присвойте результат Image.FromStream() без его клонирования: элемент управления PictureBox предпочитает действовать самостоятельно в базовом потоке (см. Источник .Net оPictureBox.Load () метод).

private void button1_Click(object sender, EventArgs e)
{
    using (FileStream stream = File.OpenRead(FullName))
    {
        pictureBox1.Image = Bitmap.FromStream(stream);
    }
    using (Graphics g = Graphics.FromImage(pictureBox1.Image))
    {
        g.Clear(Color.FromArgb(0, 255, 255, 255));
    }
}  

2) Выполните все операции внутри блока using.Поток все еще будет действителен в этой точке:

using (FileStream stream = File.OpenRead(FullName)
{
    pictureBox1.Image = (Image)Image.FromStream(stream).Clone();
    using (Graphics g = Graphics.FromImage(pictureBox1.Image))
    {
        g.Clear(Color.FromArgb(0, 255, 255, 255));
    }
}

3) Используйте метод Load () напрямую.

    pictureBox1.Load(FullName);

Все методы заканчиваются использованием внутреннего метода InstallNewImage () (источник .Net) PictureBox Control.Посмотрите, как обрабатывается изображение stream.

Вызов Graphics.FromImage() больше не вызовет исключения.

...