Не могу взять изображение из pictureBox'a для последующей проверки по пикселю

249
31 января 2018, 11:31

Не могу понять как правильно в событии MouseDoubleClick взять нарисованое Bitmap изображение и в последствии прогнать по пиксельно и изменить цвет. Подскажите пожалуйста, ссылка на проект GitHub. Сложность заключается в том что я не могу поменять цвет каждого пикселя (то есть при двойном нажатии ничего не происходит), а при попытке напрямую работать с Bitmap изображением появляется исключение (добавляю в начало события строку: bmap = new Bitmap(panel.Image);): System.NullReferenceException: 'Object reference not set to an instance of an object.'

Заранее спасибо))

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
namespace NNHopfild
{
    public partial class NNHT : Form
    {
        Point CurrentPoint;
        Graphics g;
        Bitmap bmap;
    public NNHT()
    {
        InitializeComponent();
        bmap = new Bitmap(panel.Width, panel.Height);
        panel.MouseDown += panel_MouseDown;
        panel.Paint += panel_Paint;
        g = panel.CreateGraphics();
    }
    private void exit_Click(object sender, EventArgs e)
    {
        Application.Exit();
    }
    private void panel_MouseMove(object sender, MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left)
        {
            using (Graphics g = Graphics.FromImage(bmap))
            {
                g.FillEllipse(Brushes.Black, e.X, e.Y, 10, 10);
            }
            panel.Invalidate();
        }
    }
    private void panel_MouseDown(object sender, MouseEventArgs e)
    {
        CurrentPoint = e.Location;
    }
    private void panel_Paint(object sender, PaintEventArgs e)
    {
        e.Graphics.DrawImage(bmap, Point.Empty);
    }
    private void panel_MouseDoubleClick(object sender, MouseEventArgs e)
    {
        int height = panel.Height;
        int width = panel.Width;
        int[,] mat = new int[height, width];
        for (int i = 0; i < height; i++)
        {
            for (int j = 0; j < width; j++)
            {
                Color col;
                col = bmap.GetPixel(i, j);
                if (col == Color.White)
                {
                    mat[i, j] = -1;
                    bmap.SetPixel(i, j, Color.Blue);
                }
                if (col == Color.Black)
                {
                    mat[i, j] = 1;
                    bmap.SetPixel(i, j, Color.Red);
                }
            }
        }
    }
}
}
Answer 1

Просто как пример:

Я сделал форму, где по двойному клику на picturebox рисуется квадрат

class MyForm : System.Windows.Forms.Form
{
    public MyForm()
    {
        var box = new PictureBox();
        var image = new Bitmap(500, 500);
        for (var i = 0; i < 500; i++)
            for (var j = 0; j < 500; j++)
            {
                image.SetPixel(i, j, Color.Green);
            }       
        box.Image = image;
        box.Width = 500;
        box.Height = 500;
        this.Width = 500;
        this.Height = 500;
        this.FormBorderStyle = FormBorderStyle.FixedToolWindow;
        box.MouseDoubleClick += (sender, args) =>
        {
            for (var i = -10; i < 10; i++)
            {
                for (var j = -10; j < 10; j++)
                {
                    var x = args.Location.X + i;
                    var y = args.Location.Y + j;
                    if (x >= 0 && y >= 0 && x < 500 && y < 500)
                        image.SetPixel(x, y, Color.Red);
                }
            }
            box.Refresh();
        };
        this.Controls.Add(box);
    }
}

Получилось

Answer 2

на 2ой взгляд :) давайте сравним с примером от tym32167:

  • вы создаёте изображение bmap = new Bitmap(panel.Width, panel.Height); по размеру панели, но не назначаете его соотв. контролу panel.Image = bmap; -- отсюда возникает упомянутое исключение, т.к. panel.Image у вас видимо всё ещё NULL.
  • после перерисовки нет вызова метода Control.Refresh() для принудительной перерисовки всего контрола; Можно более экономно перерисовывать: для каждой изменившейся области Control.Invalidate(Region), затем единственный Control.Update() обновит только эти области.
  • у вас в определённый момент зачем-то существует два одноимённых объекта графики: 1ый принадлежит классу формы g = panel.CreateGraphics(); и связан с контролом (т.о. будет пытаться рисовать в пустой panel.Image), а 2ой пересоздаётся для рисования эллипсов using (Graphics g = Graphics.FromImage(bmap)){ } в битмап не назначенный соотв.контролу.
READ ALSO
Перестал работать SqlDependency

Перестал работать SqlDependency

Пару дней назад данный код работал, сейчас событие OnChange не вызывается при изменении таблицыBroker Enable

198
C# печать уменьшенных изображений в высоком разрешении

C# печать уменьшенных изображений в высоком разрешении

Что нужно: открыть скан А4 (всегда будут использоваться сканы), уменьшить его размеры в 2 раза, разместить на 1/4 листа А4 и поместить результат...

246
Обработчик события CollectionChanged

Обработчик события CollectionChanged

Имеется сторонний контрол, который биндится к коллекции, имплементирующей CollectionChagnedПроблема в том что коллекция обновляется слишком часто,...

227
Перенос данных для разных СУБД в EntityFramework Migrations

Перенос данных для разных СУБД в EntityFramework Migrations

Есть приложение, использующее в качестве ORM EntityFrameworkНужно к этому приложению прикрутить миграцию БД

214