Модераторы: gambit, Partizan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Изменение картинки с помощью GDI+, Получение картинки в фоновом режиме 
V
    Опции темы
Unlocker
Дата 25.12.2008, 18:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 125
Регистрация: 2.11.2007
Где: Москва - Знаменск (Капустин Яр)

Репутация: нет
Всего: 2



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

       // Функция, принимающая Graphics с координатами копируемого прямоугольника и возвращающая Bitmap
        public static Bitmap CreateBitmapFromGraphics(Graphics graphicsSource, int x, int y, int width, int height)
        {
            //Получаем HDC (контекст устройства)
            IntPtr hDCSource = graphicsSource.GetHdc();
            //Создаем HDC, совместимый с только-что полученным
            IntPtr hDCDestination = Win32.CreateCompatibleDC(hDCSource);
            //Создаем Win32 bitmap, совместимый с HDC (полученном на первом шаге)
            IntPtr hBitmap = Win32.CreateCompatibleBitmap(hDCSource, width, height);
            //Выбираем bitmap в DC (делаем его текущим), чтобы затем рисовать на нем
            IntPtr hPreviousBitmap = Win32.SelectObject(hDCDestination, hBitmap);
            //Выполняем копирование из полученного DC во вновь созданный совместимый DC,
            //получая таким образом в совместимом bitmap?e нужную картинку
            Win32.BitBlt(hDCDestination, 0, 0, width, height, hDCSource, x, y, Win32.SRCCOPY);
            //Создаем объект System.Drawing.Bitmap
            Bitmap  bitmap = Bitmap.FromHbitmap(hBitmap);
            //Удаляем уже ненужные объекты
            Win32.DeleteObject(hDCDestination);
            Win32.DeleteObject(hBitmap);
            //Освобождаем DC
            graphicsSource.ReleaseHdc(hDCSource);
            return bitmap;
        }

        public void GetPlanWithZeroPointImage()
        {
            Graphics graph = Graphics.FromImage(mPlanWithAxes);
            graph.DrawImage(mZeroPointImage, ZeroPointPosition.X, mMainImage.Height - ZeroPointPosition.Y, mZeroPointImage.Width, mZeroPointImage.Height);
            mZeroPointShownImage = Win32.CreateBitmapFromGraphics(graph, 0, 0, mMainImage.Width, mMainImage.Height);
            graph.Dispose();
            this.pbxMainPlan.Image = mZeroPointShownImage;
        }

суть проблемы заключается в том, что код целевой функции (вторая по счету) делает картинку по размеру совпадающей с планом, но целиком залитую черным цветом. Кто-нибудь встречался с чем-либо подобным? Принимаются любые мнения и предположения. 
--------------------
"Если бы Шекспир был программистом, то фразу "To be or not to be" он написал бы так: 2b | ! 2b."
PM MAIL ICQ Skype GTalk Jabber   Вверх
Unlocker
Дата 22.1.2009, 18:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 125
Регистрация: 2.11.2007
Где: Москва - Знаменск (Капустин Яр)

Репутация: нет
Всего: 2



Задача принципиально не изменилась, только нашлось приблизительное ее решение средствами .NET
Код приведен ниже
Код

// создаем пустой Bitmap, подходящий по размеру, инициируем Graphics     
Bitmap bmp = new Bitmap(mMainImage.Width, mMainImage.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
Graphics g = Graphics.FromImage(bmp);
// рисуем на нем изображение и прочую чепуху
g.DrawImage(mMainImage, 0, 0);
g.DrawRectangle(new Pen(Color.ForestGreen), rect);
g.DrawLine(new Pen(Color.BlanchedAlmond), 0, 0, 60, 100);
// пробуем сохранить результат в другом Bitmap'е            
Bitmap bimp = new Bitmap(mMainImage.Width, mMainImage.Height, g);
bimp.Save(@"C:\Temp\1.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
// уничтожаем следы, т.е. ненужный объект Graphics
g.Dispose();


Требуются комментарии, почему при сохранении в файл мы получаем абсолютно черное изображение. с какими параметрами стоит поэкспериментировать, чтобы получать цветное изображение в файл?

Это сообщение отредактировал(а) Unlocker - 22.1.2009, 18:50
--------------------
"Если бы Шекспир был программистом, то фразу "To be or not to be" он написал бы так: 2b | ! 2b."
PM MAIL ICQ Skype GTalk Jabber   Вверх
diadiavova
Дата 22.1.2009, 19:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доктор Зло(диагност, настоящий, с лицензией и полномочиями)
****


Профиль
Группа: Модератор
Сообщений: 5821
Регистрация: 14.8.2008
Где: В Коньфпольте

Репутация: 16
Всего: 142



В девятой строке вместо 
Код

Bitmap bimp = new Bitmap(mMainImage.Width, mMainImage.Height, g);


надо писать

Код

Bitmap bimp = new Bitmap(bmp.Width, mMainImage.Height, g);



--------------------
Хочешь получить мудрый совет - читай подписи участников форумов.
Злой доктор Щасзаболит smile
PM   Вверх
Unlocker
Дата 24.1.2009, 00:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 125
Регистрация: 2.11.2007
Где: Москва - Знаменск (Капустин Яр)

Репутация: нет
Всего: 2



diadiavova, этот коммент я бы не назвал содержательным по раду причин, основная из которых та, что
mMainImage.Width == bmp.Width
что можно было заметить из 2 строки кода.
Плюс ко всему я пробовал экспериментировать с размерами области на Graphics(), но это ни к каким положительным результатам не привело.
Вопрос остается открытым.
--------------------
"Если бы Шекспир был программистом, то фразу "To be or not to be" он написал бы так: 2b | ! 2b."
PM MAIL ICQ Skype GTalk Jabber   Вверх
diadiavova
Дата 24.1.2009, 00:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доктор Зло(диагност, настоящий, с лицензией и полномочиями)
****


Профиль
Группа: Модератор
Сообщений: 5821
Регистрация: 14.8.2008
Где: В Коньфпольте

Репутация: 16
Всего: 142



Я имел в виду это. Невнимательно посмотрел.
Код

Bitmap bimp = new Bitmap(bmp);



--------------------
Хочешь получить мудрый совет - читай подписи участников форумов.
Злой доктор Щасзаболит smile
PM   Вверх
Unlocker
Дата 24.1.2009, 09:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 125
Регистрация: 2.11.2007
Где: Москва - Знаменск (Капустин Яр)

Репутация: нет
Всего: 2



Для чего создавать копию переменной bmp, если нужен ее измененный вид? Какое отношение имеет данный прием к вопросу о том, как сериализовать (сохранить в файл на диске) измененный по определнному алгоритму исходный рисунок?
тем более конструктора у класса Bitmap, принимающего в качестве параметра Bitmap нет.
А посмотрел я там, где ты написал. Но повторюсь - это к проблеме отношения не имеет.
--------------------
"Если бы Шекспир был программистом, то фразу "To be or not to be" он написал бы так: 2b | ! 2b."
PM MAIL ICQ Skype GTalk Jabber   Вверх
diadiavova
Дата 24.1.2009, 09:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доктор Зло(диагност, настоящий, с лицензией и полномочиями)
****


Профиль
Группа: Модератор
Сообщений: 5821
Регистрация: 14.8.2008
Где: В Коньфпольте

Репутация: 16
Всего: 142



Цитата(Unlocker @  24.1.2009,  09:13 Найти цитируемый пост)
Для чего создавать копию переменной bmp, если нужен ее измененный вид?


Если этот код выполнить после того, как первая переменная будет изменена, то копия будет содержать все изменения(в первом посте я указал, что это надо выполнить в 9-й строке твоего примера). Для чего создавать копию, когда изменённый оригинал можно сохранить напрямую - тебе виднее, я только отвечаю на твой вопрос, ты в коде перед сохранением зачем-то пытался сначала скопировать рисунок, а просто показал как это надо делать.

Цитата(Unlocker @  24.1.2009,  09:13 Найти цитируемый пост)
Какое отношение имеет данный прием к вопросу о том, как сериализовать (сохранить в файл на диске) измененный по определнному алгоритму исходный рисунок?

Никакого. Это делается методом Save. У тебя это не сработало только потому, что ты сохранил не изменённый рисунок, а вновь созданный.


Цитата(Unlocker @  24.1.2009,  09:13 Найти цитируемый пост)
тем более конструктора у класса Bitmap, принимающего в качестве параметра Bitmap нет.

У него есть конструктор, принимающий Image(посмотри иерархию наследования Bitmap). 
Цитата(Unlocker @  24.1.2009,  09:13 Найти цитируемый пост)
А посмотрел я там, где ты написал.

Я написал, что я невнимательно посмотрел твой код перед тем как его исправить. 




Это сообщение отредактировал(а) diadiavova - 24.1.2009, 09:31


--------------------
Хочешь получить мудрый совет - читай подписи участников форумов.
Злой доктор Щасзаболит smile
PM   Вверх
Unlocker
Дата 24.1.2009, 16:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 125
Регистрация: 2.11.2007
Где: Москва - Знаменск (Капустин Яр)

Репутация: нет
Всего: 2



Насколько мне известно Bitmap можно изменить только методом SetPixel(Color).
Меня же интересует сохранение в виде класса Bitmap содержимого экземпляра Graphics. Карта bmp после метода Graphics.FromImagr(bmp) не изменяется или я что-то не так понимаю?
--------------------
"Если бы Шекспир был программистом, то фразу "To be or not to be" он написал бы так: 2b | ! 2b."
PM MAIL ICQ Skype GTalk Jabber   Вверх
diadiavova
Дата 24.1.2009, 17:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доктор Зло(диагност, настоящий, с лицензией и полномочиями)
****


Профиль
Группа: Модератор
Сообщений: 5821
Регистрация: 14.8.2008
Где: В Коньфпольте

Репутация: 16
Всего: 142



Цитата(Unlocker @  24.1.2009,  16:43 Найти цитируемый пост)
Насколько мне известно Bitmap можно изменить только методом SetPixel(Color).

Очень странное предполжение, особенно если учесть, что ты сам в своём же примере изменял битмап при помощи объекта Graphics.
Цитата(Unlocker @  22.1.2009,  18:40 Найти цитируемый пост)

Graphics g = Graphics.FromImage(bmp);
// рисуем на нем изображение и прочую чепуху
g.DrawImage(mMainImage, 0, 0);
g.DrawRectangle(new Pen(Color.ForestGreen), rect);
g.DrawLine(new Pen(Color.BlanchedAlmond), 0, 0, 60, 100);


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

// создаем пустой Bitmap, подходящий по размеру, инициируем Graphics     
Bitmap bmp = new Bitmap(mMainImage.Width, mMainImage.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
Graphics g = Graphics.FromImage(bmp);
// рисуем на нем изображение и прочую чепуху
g.DrawImage(mMainImage, 0, 0);
g.DrawRectangle(new Pen(Color.ForestGreen), rect);
g.DrawLine(new Pen(Color.BlanchedAlmond), 0, 0, 60, 100);
// пробуем сохранить результат в другом Bitmap'е            
bmp.Save(@"C:\Temp\1.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
// уничтожаем следы, т.е. ненужный объект Graphics
g.Dispose();


Здесь я привёл твой исправленный код.


Это сообщение отредактировал(а) diadiavova - 24.1.2009, 17:33


--------------------
Хочешь получить мудрый совет - читай подписи участников форумов.
Злой доктор Щасзаболит smile
PM   Вверх
Unlocker
Дата 25.1.2009, 00:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 125
Регистрация: 2.11.2007
Где: Москва - Знаменск (Капустин Яр)

Репутация: нет
Всего: 2



Спасибо за разъяснения!  smile 
Теперь более или менее понятно. Хотя при прорисовки контролов, например, Graphics выступает в роли бумаги. А в оффициальном МСДН разница между работой с методами FromImage и CreateGraphics не пояснена.
Теперь можно нормально выполнить свою задумку. Еще раз спасибо, diadiavova, за подробные объяснения. smile 
--------------------
"Если бы Шекспир был программистом, то фразу "To be or not to be" он написал бы так: 2b | ! 2b."
PM MAIL ICQ Skype GTalk Jabber   Вверх
diadiavova
Дата 25.1.2009, 01:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доктор Зло(диагност, настоящий, с лицензией и полномочиями)
****


Профиль
Группа: Модератор
Сообщений: 5821
Регистрация: 14.8.2008
Где: В Коньфпольте

Репутация: 16
Всего: 142



В контролах он играет ту же самую роль. Разница в том, что один метод (CreateGraphics) создаёт объект для прорисовки в контроле, а другой в изображении(Bitmap или Metafile). Прорисовав в контроле рисунок при помощи Graphics, ты точно так же не сможешь использовать Graphics для сохранения нарисованного. Толькодля рисования (всё-таки карандаш  smile )


--------------------
Хочешь получить мудрый совет - читай подписи участников форумов.
Злой доктор Щасзаболит smile
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Разработка Windows Forms | Следующая тема »


 




[ Время генерации скрипта: 0.1168 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.