Форум программистов, компьютерный форум, киберфорум
Visual Basic .NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.78/9: Рейтинг темы: голосов - 9, средняя оценка - 4.78
 Аватар для jkrnd
179 / 69 / 13
Регистрация: 22.12.2015
Сообщений: 2,648

Как средствами GDI+ нарисовать тень для прозрачной картинки

27.02.2016, 13:42. Показов 2021. Ответов 13
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Имеется картинка с прозрачным фоном (ico, png).Пусть она вставлена в Picturebox. Как её перерисовать со смещением на один пиксел вправо и вниз таким образом, чтобы все непрозрачные пиксели были заменены на цвет, допустим, color.Gray. А уж затем сверху созданной "тени" наложить оригинал. Заранее спасибо за совет "переходите на WPF".
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
27.02.2016, 13:42
Ответы с готовыми решениями:

Нарисовать скобку средствами GDI+
Нужно нарисовать круглую скобку с утолщенной серединой (см. картинку). Ясно, что ее можно нарисовать используя метод DrawString. А как...

Нарисовать определенную фигуру средствами GDI+
Необходимо нарисовать такую фигуру(с заливкой). Для построения даны угловые точки и радиус кривизны. Построение кривизны сводиться к...

Как задать тень для таблицы средствами CSS?
Подскажите как задать тень для таблицы средствами CSS? Только желательно класс указывать в теге <table>, а не в строках и...

13
4708 / 3661 / 857
Регистрация: 02.02.2013
Сообщений: 3,518
Записей в блоге: 2
28.02.2016, 01:06
Лучший ответ Сообщение было отмечено jkrnd как решение

Решение

Как то так
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
Private dx As Integer = 3
Private dy As Integer = 3
Private bmp1 As Bitmap
Private Sub Button3_Click(sender As System.Object, e As System.EventArgs) Handles Button3.Click
    bmp1 = loadBitmap("tst2.png")
    Dim bmp2 As Bitmap = bmp1.Clone
    Dim w As Integer = bmp1.Width
    Dim h As Integer = bmp1.Height
    Dim cm As ColorMatrix = New ColorMatrix(New Single()() _
                   {New Single() {0, 0, 0, 0, 0}, _
                    New Single() {0, 0, 0, 0, 0}, _
                    New Single() {0, 0, 0, 0, 0}, _
                    New Single() {0, 0, 0, 0.25, 0}, _
                    New Single() {0, 0, 0, 0, 1}})
    Dim imgattr As New ImageAttributes()
    Dim rc As New Rectangle(dx, dy, w, h)
    Dim g As Graphics = PictureBox1.CreateGraphics
    imgattr.SetColorMatrix(cm)
    g.DrawImage(bmp2, rc, 0, 0, w, h, GraphicsUnit.Pixel, imgattr)
    Dim rc1 As New Rectangle(0, 0, w, h)
    g.DrawImage(bmp1, rc1, 0, 0, w, h, GraphicsUnit.Pixel)
    g.Dispose()
End Sub
Public Function loadBitmap(ByVal fileName As String) As Bitmap
    If Not IO.File.Exists(fileName) Then Return Nothing
    Using bm As Bitmap = New Bitmap(fileName)
        Return New Bitmap(bm)
    End Using
End Function
Изображения
 
4
 Аватар для jkrnd
179 / 69 / 13
Регистрация: 22.12.2015
Сообщений: 2,648
28.02.2016, 05:11  [ТС]
ovva, Спасибо. Всё работает как нужно. Нельзя ли упростить задание цвета тени? Вместо инициализации ColorMatrix задавать цвет тени обычным способом (color.Gray), Поменять все непрозрачные пиксели на color.Gray.

Добавлено через 1 час 4 минуты
ovva, помогите пожалуйста изменить Ваш код под мою задачу:
VB.NET
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
bmp2 = fnShade(bmp1, PictureBox1)
 
Public Function fnShade(ByVal bmp As Bitmap, ByVal pbx As PictureBox) As Bitmap
        fnShade = bmp 'по-умолчанию картинка не изменяется
        'задаём цвет тени 4-я строка, 4-й столбец
        Dim cm As ColorMatrix = New ColorMatrix(New Single()() _
                       {New Single() {0, 0, 0, 0, 0}, _
                        New Single() {0, 0, 0, 0, 0}, _
                        New Single() {0, 0, 0, 0, 0}, _
                        New Single() {0, 0, 0, 0.5, 0}, _
                        New Single() {0, 0, 0, 0, 1}})
        Dim imgattr As New ImageAttributes()
        imgattr.SetColorMatrix(cm)
        Dim rc As New Rectangle(0, 0, bmp.Width, bmp.Height)
        Dim g As Graphics = pbx.CreateGraphics
        g.DrawImage(bmp, rc, 0, 0, bmp.Width, bmp.Height, GraphicsUnit.Pixel, imgattr)
        g.Dispose()
End Function
Как убрать из аргументов функции fnShadow элемент ByVal pbx As PictureBox?
0
4708 / 3661 / 857
Регистрация: 02.02.2013
Сообщений: 3,518
Записей в блоге: 2
28.02.2016, 13:48
Лучший ответ Сообщение было отмечено jkrnd как решение

Решение

Упростить решение наверное можно. Реальные, на мой взгляд, варианты:
• Если картинка небольшая, то возможно просто просканировать все пиксели и изменить их как нужно.
• Использовать BitBlt из GDI.
Внес изменения в код. Не знаю, насколько он отвечает вашей задаче.
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 Button4_Click(sender As System.Object, e As System.EventArgs) Handles Button4.Click
    bmp1 = loadBitmap("tst2.png")
    Dim newBmp As Bitmap = fnShade(bmp1)
    PictureBox1.Image = newBmp
End Sub
Private Function fnShade(ByVal bmp As Bitmap) As Bitmap
    Dim w As Integer = bmp1.Width
    Dim h As Integer = bmp1.Height
    Dim myBmp As New Bitmap(w + dx, h + dy, Imaging.PixelFormat.Format32bppArgb)
    Dim g As Graphics = Graphics.FromImage(myBmp)
    Dim cm As ColorMatrix = New ColorMatrix(New Single()() _
           {New Single() {0, 0, 0, 0, 0}, _
            New Single() {0, 0, 0, 0, 0}, _
            New Single() {0, 0, 0, 0, 0}, _
            New Single() {0, 0, 0, 0.5, 0}, _
            New Single() {0, 0, 0, 0, 1}})
    Dim imgattr As New ImageAttributes()
    Dim rc As New Rectangle(dx, dy, w, h)
    imgattr.SetColorMatrix(cm)
    g.DrawImage(bmp.Clone, rc, 0, 0, w, h, GraphicsUnit.Pixel, imgattr)
    Dim rc1 As New Rectangle(0, 0, w, h)
    g.DrawImage(bmp1, rc1, 0, 0, w, h, GraphicsUnit.Pixel)
    g.Dispose()
    Return myBmp
End Function
2
 Аватар для jkrnd
179 / 69 / 13
Регистрация: 22.12.2015
Сообщений: 2,648
28.02.2016, 14:06  [ТС]
Цитата Сообщение от ovva Посмотреть сообщение
Использовать BitBlt из GDI
Всё ОК. Спасибо. Ваш код гораздо лучше чем, попиксельная перерисовка прямоугольника через API, что я и делал когда-то на VB-6. Пытался в msdn найти объяснения для элементов матрицы ColorMatrix, какое значение за что отвечает, не понял ничего. Если есть ссылка на более толковый help, сбросьте пожалуйста. Или подскажите своими словами. Наверняка эта матрица используется и для анимации. Пока меняю значения в матрице методом научного тыка.
0
4708 / 3661 / 857
Регистрация: 02.02.2013
Сообщений: 3,518
Записей в блоге: 2
28.02.2016, 18:40
Лучший ответ Сообщение было отмечено jkrnd как решение

Решение

Вариант перекрашивания картинки в нужный цвет (если использование ColorMatrix вызывает проблемы).
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
Private Sub Button5_Click(sender As System.Object, e As System.EventArgs) Handles Button5.Click
    bmp1 = loadBitmap("tst2.png")
    Dim newColorBmp As Bitmap = toNewColor(bmp1.Clone, Color.Gray)
    PictureBox1.Image = newColorBmp
End Sub
Private Function toNewColor(ByVal bmp As Bitmap, ByVal clr As Color) As Bitmap
    If bmp.PixelFormat <> PixelFormat.Format32bppArgb Then Return Nothing
    Dim rect As New Rectangle(0, 0, bmp.Width, bmp.Height)
    Dim bmpData As BitmapData = bmp.LockBits(rect, Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat)
    Dim ptr As IntPtr = bmpData.Scan0
    Dim allbytes As Integer = bmpData.Stride * bmp.Height
    Dim rgbV(allbytes - 1) As Byte
    System.Runtime.InteropServices.Marshal.Copy(ptr, rgbV, 0, allbytes)
    For i = 0 To allbytes - 1 Step 4
        If rgbV(i + 3) > 0 Then
            rgbV(i) = clr.B
            rgbV(i + 1) = clr.G
            rgbV(i + 2) = clr.R
        End If
    Next
    System.Runtime.InteropServices.Marshal.Copy(rgbV, 0, ptr, allbytes)
    bmp.UnlockBits(bmpData)
    Return bmp
End Function
2
 Аватар для jkrnd
179 / 69 / 13
Регистрация: 22.12.2015
Сообщений: 2,648
28.02.2016, 19:10  [ТС]
ovva, Спасибо. Всё работает. Я так понял, что это попиксельная замена?
Кстати в предыдущем варианте (Function fnShade(ByVal bmp As Bitmap) As Bitmap) если работать с отрицательными сдвигами dx, dy тень улетает за пределы левого верхнего угла PictureBox.
0
4708 / 3661 / 857
Регистрация: 02.02.2013
Сообщений: 3,518
Записей в блоге: 2
28.02.2016, 19:36
это попиксельная замена?
Вообщем да, но достаточно быстрая.
если работать с отрицательными сдвигами dx, dy
Напомню постановку задачи
перерисовать со смещением на один пиксел вправо и вниз
2
 Аватар для jkrnd
179 / 69 / 13
Регистрация: 22.12.2015
Сообщений: 2,648
28.02.2016, 19:44  [ТС]
ovva, Вы правы, задача решена полностью. Огромное спасибо.
0
Модератор
Эксперт .NET
 Аватар для Yury Komar
4358 / 3428 / 512
Регистрация: 27.01.2014
Сообщений: 6,258
29.02.2016, 14:07
ovva, не подскажете, а как составить свою матрицу для конкретной задачи? Не подскажете описание сего чуда?
0
4708 / 3661 / 857
Регистрация: 02.02.2013
Сообщений: 3,518
Записей в блоге: 2
29.02.2016, 22:30
В Google можно найти достаточно много описаний ColorMatrix правда, большинство из них сводятся к описанию конкретных примеров.
http://stackoverflow.com/quest... ith-vb-net
http://www.vbforums.com/showth... icture-box
http://www.codeproject.com/Art... Adjustment
http://stackoverflow.com/quest... olormatrix
http://www.xtremevbtalk.com/-n... white.html
http://www.codeproject.com/Art... ng-Effects
http://www.techrepublic.com/bl... e-using-c/
и т.д. Список можно продолжать и продолжать. Несколько более общее описание можно найти здесь http://foxclub.ru/vfpbook/gl23/colormatrix.htm. Для понимания как это работает, на мой взгляд, целесообразнее обратиться к разделу цветовая оптика.
Для удобства проведения опытов с ColorMatrix написал небольшую программку.
Миниатюры
Как средствами GDI+ нарисовать тень для прозрачной картинки  
Вложения
Тип файла: zip ColorMatrixTest.zip (16.3 Кб, 18 просмотров)
5
4708 / 3661 / 857
Регистрация: 02.02.2013
Сообщений: 3,518
Записей в блоге: 2
02.03.2016, 21:54
Добавлю еще пару ссылок
https://msdn.microsoft.com/en-... s.85).aspx
https://docs.rainmeter.net/tips/colormatrix-guide/
2
85 / 75 / 15
Регистрация: 18.01.2014
Сообщений: 359
10.01.2020, 10:35
ovva, извините, но ваша программа ColorMatrixTest не работает, пишет ошибку System.InvalidCastException: Conversion from string "0.0" to type 'Single' is not valid. ---> System.FormatException: Input string was not in a correct format.

Может исходник выложите?
0
4708 / 3661 / 857
Регистрация: 02.02.2013
Сообщений: 3,518
Записей в блоге: 2
10.01.2020, 14:19
Цитата Сообщение от _Radik_ Посмотреть сообщение
но ваша программа ColorMatrixTest не работает
Проверил, все работает. Судя по ошибке, проблема достаточно типичная, скорее всего у вас в системе установлен десятичный разделитель запятая (,).
В коде нет ничего особенного и выложить бы не проблема, но в проекте еще куча разных тестов и выпиливать оттуда как то нет желания.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
10.01.2020, 14:19
Помогаю со студенческими работами здесь

Заливка средствами GDI+ как в paint
как можно при помощи GDI+ залить область, ограниченную кривыми, как в paint?

Как сделать падающюю тень от картинки.
Подскажите плизззз, как или в каком формате сохранить изображение, что бы тень от картинки, которую я сделал в Фотошопе, осталась. Уточняю:...

как нарисовать стрелку в GDI+?
Кто-нибудь подскажите как нарисовать стрелку.я нарисовал линию, теперь чтобы получилась стрелка мне надо построить треугольник на конце...

Как нарисовать кнопку с помощью GDI+?
Всем привет! Несколько дней назад ко мне в голову пришла мысль можно ли нарисовать работающую кнопку через GDI+ &amp; C#. У меня есть...

Как через GDI нарисовать пиксел на окне?
Как через GDI нарисовать пиксел на окне?


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
14
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru