Все технические форумы на одном сайте Удобный поиск информации с популярных форумов в одном месте
Вопрос: PictureBox, Graphics и оттенки серого

Здравствуйте, форумчане! Проблема в следующем. Если создаю рисунок:
C#
1
Image img = new Bitmap(sizeX, sizeY);
То могу его применить в качестве рисунка для PictureBox, а также в объекте Graphics.
Но если создаю рисунок вот так:
C#
1
Image img = new Bitmap(sizeX, sizeY, PixelFormat.Format16bppGrayScale);
То в коде:
C#
1
pictureBoxMap.Image = img;
а также в:
C#
1
Graphics g = Graphics.FromImage(img);
выдает ошибку:
Необработанное исключение типа "System.OutOfMemoryException" в System.Drawing.dll

Дополнительные сведения: Недостаточно памяти.
Подскажите, где я ошибаюсь? Может есть какая-то настройка в PictureBox и в Graphics?

P.S. Мне нужно работать именно с 16-битным изображением в оттенках серого.
Ответ: some_name, спасибо за быстрый ответ. Буду разбираться или искать другое решение.
Вопрос: Выбрать оттенки серого из текста

Выбрать оттенки серого из текста в разных цветовых системах. Как это вообще делается, помогите пожалуйста...
Ответ:

Не по теме:

штук 50 оттенков серого нужно небось?

Вопрос: Преобразование изображения к оттенкам серого

Здравствуйте! Очень нужна помощь) Пишу приложение, которое делает выделение контуров на изображении методом Робертса. Для начала нужно преобразовать его цвета в оттенки серого. Делаю это вот так:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
private void button2_Click(object sender, EventArgs e)
        {
            //перевод в серые тона
            if (pictureBox1.Image == null)
            {
                MessageBox.Show("Изображение отсутствует!");
                return;
            }
            Bitmap grayImg = new Bitmap(image);
            Graphics g = Graphics.FromImage(grayImg);
            ColorMatrix colorMatrix = new ColorMatrix(new float[][]
            {new float[] {3f, 3f, 3f, 0, 0},
             new float[] {59f, 59f, 59f, 0, 0},
             new float[] {11f, 11f, 11f, 0, 0},
             new float[] {0, 0, 0, 1, 0},
             new float[] {0, 0, 0, 0, 1}
            });
            ImageAttributes attributes = new ImageAttributes();
            attributes.SetColorMatrix(colorMatrix);
            g.DrawImage(pictureBox1.Image,
            new Rectangle(0, 0, pictureBox1.Image.Width, pictureBox1.Image.Height), 0, 0,
            pictureBox1.Image.Width, pictureBox1.Image.Height,
            GraphicsUnit.Pixel, attributes);
            g.Dispose();
            pictureBox1.Image = grayImg;
        }
Но вместо преобразования в оттенки серого изображение просто засвечивается, становится практически полностью белым. Можете, пожалуйста, указать, в чём ошибка и как исправить? Я в обработке изображений новичок, разбираюсь только)
Для удобства в архиве весь проект.
Ответ: Точно! Спасибо)
Вопрос: Изображение в оттенки серого

Здравствуйте! Помогите, пожалуйста.
Дело в том, что мне необходимо перевести изображение в оттенки серого, потом применять на него матричные фильтры.
Но после перевода и применения размытия изображение вновь становится цветным.
Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
public static UInt32[,] matrix_filtration(int W, int H, UInt32[,] pixel, int N, double[,] matryx)
            {
                int i, j, k, m, gap = (int)(N / 2);
                int tmpH = H + 2 * gap, tmpW = W + 2 * gap;
                UInt32[,] tmppixel = new UInt32[tmpH, tmpW];
                UInt32[,] newpixel = new UInt32[H, W];
                //заполнение временного расширенного изображения
                //углы
                for (i = 0; i < gap; i++)
                    for (j = 0; j < gap; j++)
                    {
                        tmppixel[i, j] = pixel[0, 0];
                        tmppixel[i, tmpW - 1 - j] = pixel[0, W - 1];
                        tmppixel[tmpH - 1 - i, j] = pixel[H - 1, 0];
                        tmppixel[tmpH - 1 - i, tmpW - 1 - j] = pixel[H - 1, W - 1];
                    }
                //крайние левая и правая стороны
                for (i = gap; i < tmpH - gap; i++)
                    for (j = 0; j < gap; j++)
                    {
                        tmppixel[i, j] = pixel[i - gap, j];
                        tmppixel[i, tmpW - 1 - j] = pixel[i - gap, W - 1 - j];
                    }
                //крайние верхняя и нижняя стороны
                for (i = 0; i < gap; i++)
                    for (j = gap; j < tmpW - gap; j++)
                    {
                        tmppixel[i, j] = pixel[i, j - gap];
                        tmppixel[tmpH - 1 - i, j] = pixel[H - 1 - i, j - gap];
                    }
                //центр
                for (i = 0; i < H; i++)
                    for (j = 0; j < W; j++)
                        tmppixel[i + gap, j + gap] = pixel[i, j];
                //применение ядра свертки
                RGB ColorOfPixel = new RGB();
                RGB ColorOfCell = new RGB();
                for (i = gap; i < tmpH - gap; i++)
                    for (j = gap; j < tmpW - gap; j++)
                    {
                        ColorOfPixel.R = 0;
                        ColorOfPixel.G = 0;
                        ColorOfPixel.B = 0;
                        for (k = 0; k < N; k++)
                            for (m = 0; m < N; m++)
                            {
                                ColorOfCell = calculationOfColor(tmppixel[i - gap + k, j - gap + m], matryx[k, m]);
                                ColorOfPixel.R += ColorOfCell.R;
                                ColorOfPixel.G += ColorOfCell.G;
                                ColorOfPixel.B += ColorOfCell.B;
                            }
                        //контролируем переполнение переменных
                        if (ColorOfPixel.R < 0) ColorOfPixel.R = 0;
                        if (ColorOfPixel.R > 255) ColorOfPixel.R = 255;
                        if (ColorOfPixel.G < 0) ColorOfPixel.G = 0;
                        if (ColorOfPixel.G > 255) ColorOfPixel.G = 255;
                        if (ColorOfPixel.B < 0) ColorOfPixel.B = 0;
                        if (ColorOfPixel.B > 255) ColorOfPixel.B = 255;
 
                        newpixel[i - gap, j - gap] = build(ColorOfPixel);
                    }
 
                return newpixel;
            }
 
            //вычисление нового цвета
            public static RGB calculationOfColor(UInt32 pixel, double coefficient)
            {
                RGB Color = new RGB();
                Color.R = (float)(coefficient * ((pixel & 0x00FF0000)>>16)); //>>16
                Color.G = (float)(coefficient * ((pixel & 0x0000FF00) >>8));//>>8
            Color.B = (float)(coefficient * ((pixel & 0x000000FF)));
                return Color;
            }
 
            //сборка каналов
            public static UInt32 build(RGB ColorOfPixel)
            {
                UInt32 Color;
                Color = ((UInt32)ColorOfPixel.R << 16) | ((UInt32)ColorOfPixel.G << 8) | ((UInt32)ColorOfPixel.B);
                return Color;
            }
 
            public const int N = 3;
            public static double[,] blur = new double[N, N] {{0.111,0.111,0.111},
                                                          { 0.111,0.111,0.111},
                                                          { 0.111,0.111,0.111}};
        public void Gray(PictureBox pb)
        {
            int brg;
            Bitmap bmp = new Bitmap(pb.Image);
            for (int i = 1; i < bmp.Width; i++)
            {
                for (int j = 1; j < bmp.Height; j++)
                {
                    brg = (int)(0.3 * bmp.GetPixel(i, j).R + 0.59 * bmp.GetPixel(i, j).G + 0.11 * bmp.GetPixel(i, j).B);
                    bmp.SetPixel(i, j, Color.FromArgb(brg, brg, brg));
                }
            }
            pb.Image = bmp;
            
        }
        private void размытиеToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (nameofimage!="/0")
            {
                pixel = Filter.matrix_filtration(image.Width, image.Height, pixel, Filter.N, Filter.blur);
                FromPixelToBitmap();
                FromBitmapToScreen();
            }
        }
 
        private void матричныйФильтрToolStripMenuItem_Click(object sender, EventArgs e)
        {
            W W = new W();
            W.Show();
        }
 
        private void menuStrip1_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {
 
        }
 
        private void оттенкиСерогоToolStripMenuItem_Click(object sender, EventArgs e)
        {
           obj.Gray(pictureBox1);
            FromPixelToBitmap();
        }
        public static void FromPixelToBitmap()
        {
            for (int y = 0; y < image.Height; y++)
                for (int x = 0; x < image.Width; x++)
                    image.SetPixel(x, y, Color.FromArgb((int)pixel[y, x]));
        }
 
        //вывод на экран
        public void FromBitmapToScreen()
        {
            pictureBox1.Image = image;
        }

Прикрепил саму программу
Помогите, пожалуйста, совсем не понимаю, что не так.
Ответ:
Вопрос: Создать 256 оттенков серого из любой картинки

Доброго времени суток. Существует задача зашифровки небольшого изображения. Для этого нужно знать значение градации серого (0(белый)-255(черный)) каждого пикселя.

Есть проблема. Любую картинку я могу переделать в Черно-белую с 256 оттенками серого в фотошопе, но тогда, я не знаю, как узнать конкретное значение(0-255) конкретного пикселя имея только параметры RGB

Если же переделывать цветную картину в Черно-белую программно, то картинка будет иметь гораздо больше оттенков серого!

Подскажите, как мне решить данную проблему. Может способ переделки цветной картинки в чернобелую можно изменить?
Код C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Bitmap img = new Bitmap(textBoxFilePath.Text);
 
            for (int i = 0; i < img.Width; i++)
            {
                for (int j = 0; j < img.Height; j++)
                {
                    Color pixel = img.GetPixel(i, j);
                   
                    int grayScale = (int)((pixel.R * .3) + (pixel.G * .59)
                        + (pixel.B * .11));
 
                   
                    Color nColor = Color.FromArgb(grayScale, grayScale, grayScale);
 
                    //set the new image's pixel to the grayscale version
                   img.SetPixel(i, j, nColor);
                }
            }
Добавлено через 7 минут
Немного не разобрался в оттенках серого. Я так понял их всего 256?

Тогда как можно привязать конкретный пиксель к конкретному значению (0-255) ?

Добавлено через 17 минут
разобрался, нашел формулу!
Код C#
1
H[i, j] = Convert.ToInt32(pixel.R * 0.2126 + pixel.G * 0.7152 + pixel.B * 0.0722);
Ответ:
Сообщение от goyt
Код C#
1
H[i, j] = Convert.ToInt32(pixel.R * 0.2126 + pixel.G * 0.7152 + pixel.B * 0.0722);
Код C#
1
H[i, j] = 255 - Convert.ToInt32(pixel.R * 0.2126 + pixel.G * 0.7152 + pixel.B * 0.0722);
Вопрос: Привести изображение к оттенкам серого и получить одномерный массив зачений его пикселей

Здравствуйте. Модифицируйте пожалуйста код так, чтобы получаемое на данном этапе разработки изображение привелось к оттенкам серого. И получить одномерный массив значений яркости пикселей.

vb.net
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
Option Strict On
Imports System.Drawing
Public Class Form1
 
    Private Sub Form1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Click
        Dim x, Y, c, r, g, b, threshold As Integer
        Dim blackPen As New Pen(Color.Black, 1)
        Dim whitePen As New Pen(Color.White, 1)
        Dim tempPen As Pen
        Dim myGraphics As Graphics = MyBase.CreateGraphics()
        Dim bmp As New Bitmap("C:\x40.png")
 
        threshold = 20
        Me.Height = bmp.Height + 5
        Me.Width = bmp.Width + 5
        For Y = 0 To bmp.Height - 1
            For x = 0 To bmp.Width - 1
 
                r = bmp.GetPixel(x, Y).R
                g = bmp.GetPixel(x, Y).G
                b = bmp.GetPixel(x, Y).B
 
                If (r - b) > threshold And (r - g) > threshold Then
 
                    tempPen = New Pen(bmp.GetPixel(x, Y), 1)
                    myGraphics.DrawEllipse(tempPen, x, Y, 1, 1)
                Else
                    myGraphics.DrawEllipse(whitePen, x, Y, 1, 1)
                End If
 
            Next
        Next
 
    End Sub
 
End Clas
Ответ:
Сообщение от ovva
и что такое "правильное"?
изображение, имеющее множество значений тона, и их непрерывное, плавное изменение.
Вопрос: Qt и диалог выбора оттенков серого

QColorDialog показывает палитру цветов и позволяет выбрать там нужный. А нет ли какого-то готового виджета делающего тоже самое, но для оттенков серого?
Ответ: Renji, Дык, там все-го то 256 = 16 х 16 цветов. Сделал 256 квадратиков - выбирай в свое удовольствие...

Добавлено через 8 минут
Еще можно шкалу прозрачности добавить - и хоть на выставку
Вопрос: Фильтр градиент серого

Добрый день, помогите пожалуйста реализовать задачу. Нужно написать фильтр оттенок серого для изображения с помощью scanline.Подскажите что написать в середине цикла?
C++
1
2
3
4
5
6
7
8
9
10
11
Graphics::TBitmap *Bitmap=new Graphics::TBitmap();
Bitmap->Assign(Form1->Image1->Picture->Graphic);
  for(int y = 0; y < Bitmap->Height; y++)
  {
    ptr = (Byte*)Bitmap->ScanLine[y];
    for (int x = 0; x < Bitmap->Width; x++)
    {
     ???????????
    }
  }
  Form1->Image1->Canvas->Draw(0, 0, Bitmap);
Ответ: Спасибо,разобралса еще вчера
Вопрос: Как рисовать на PictureBox'e, созданным программным способом (динамически)

Приветствую всех.
При создании объекта PictureBox динамическим способом, почему-то на нем не отображаются элементы Graphics. Уже не знаю что делать, чего только не перепробовал. При этом, если создавать пикчрбокс через панель инструментов, то все работает. Но мне как раз нужно создавать бокс программно.

vb.net
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
 
        Dim pic as New PictureBox
 
        Dim gra As Graphics
 
        With pic
            .SizeMode = PictureBoxSizeMode.AutoSize
            .Size = New Size(400, 300)
            .Location = New Point(100, 100)
            .Visible = True
            .BackColor = Color.Aqua
            '.Show()
        End With
        
        Me.Controls.Add(pic)  'pic на форме отображается нормально
 
        gra = pic.CreateGraphics()
 
        gra.DrawLine(Pens.Black, 20, 20, 300, 300) 'а вот эту строку будто игнорирует
        'ни один элемент graphics не отображается
 
        pic.Refresh()
 
    End Sub
В чем здесь ошибка? Не откажите в помощи начинающему программисту . Заранее спасибо.
Ответ: OldFedor, зачем нужны следующие команды (строки 10 и 12):
vb.net
1
Dim grf As Graphics = pic.CreateGraphics
vb.net
1
grf.DrawImage(hlst, 0, 0)
всё будет работать и так:
vb.net
1
2
3
4
5
6
7
8
9
10
11
12
       
        Dim pic As New PictureBox, hlst As Bitmap
        With pic
            .SizeMode = PictureBoxSizeMode.AutoSize
            .Size = New Size(400, 300) : .Location = New Point(100, 100)
            .Visible = True : .BackColor = Color.Aqua
        End With
        hlst = New Bitmap(pic.ClientSize.Width, pic.ClientSize.Height)
        Me.Controls.Add(pic)  'pic на форме отображается нормально
        Dim graph As Graphics = Graphics.FromImage(hlst)
        graph.DrawLine(Pens.Black, 20, 20, 300, 300) 'а вот эту строку будто игнорирует
        pic.Image = hlst
Вопрос: Рисование в PictureBox и сохранение рисунка

Создается простой графический редактор на C#.

Проблема следующая: в PictureBox загружается рисунок из файла. Пользователь рисует в PictureBox поверх рисунка различные кривые (что-вроде "кисти" или "карандаша"). При попытке сохранить измененный рисунок сохраняется исходный, который был загружен.

Как я понимаю, проблема в том, что я рисую на самом компоненте PictureBox, а не на Image. Отсюда вопрос - как изменять Image компонента PictureBox или как сохранить то, что нарисовано прямо на компоненте?
Ответ: А как это можно реализовать не в MouseMove, а в MouseUp? Чтобы рисовать например прямоугольник или квадрат? я сделал в MouseMove, но получились прямоугольники в прямоугольнике, а когда вставляю эту строку
Код C#
1
Graphics g = Graphics.FromImage(pictureBox1.Image);
в MouseUp он у меня не рисует поверх картинки
Сообщение от Стасёнок
Лучше при загрузке картинки сделать её битмапом:

Код C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 private void открытьToolStripMenuItem_Click(object sender, EventArgs e)
{
 OpenFileDialog dialog = new OpenFileDialog();
 dialog.Filter = "Image files (*.BMP, *.JPG, *.GIF, *.TIF, *.PNG, *.ICO, *.EMF, *.WMF)|*.bmp;*.jpg;*.gif; *.tif; *.png; *.ico; *.emf; *.wmf";
 if (dialog.ShowDialog() == DialogResult.OK)
 {
Image image = Image.FromFile(dialog.FileName);
int width = image.Width;
 int height = image.Height;
pictureBox1.Width = width;
pictureBox1.Height = height;
[B]bmp = new Bitmap(Image.FromFile(dialog.FileName), width, height);
pictureBox1.Image = bmp;[/B]
}
 }
Далее, рисуя карандашом в событии pictureBox1_MouseMove:
Код C#
1
2
3
4
5
6
7
8
9
10
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
Pen blackPen = new Pen(currentColor, 1);
// Рисовать так: 
Graphics g = Graphics.FromImage(pictureBox1.Image);
g.DrawLine(blackPen, PreviousPoint, point);
blackPen.Dispose();
g.Dispose();
pictureBox1.Invalidate();
}