
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[216.73.216.234] |
![]() |
|
Страницы: (2) [1] 2 все ( Перейти к последнему сообщению ) |
Сообщ.
#1
,
|
|
|
Привет всем!
У меня задача, сделать по сути многофункциональную рисовалку на основе PaintBox. Подскажите, где много хорошей инфы лежит? ![]() |
Сообщ.
#2
,
|
|
|
trosh - какую рисовалку - векторную или растровую?
|
Сообщ.
#3
,
|
|
|
Цитата Coala @ trosh - какую рисовалку - векторную или растровую? за неделю с векторами точтно не успею, растровую бы успеть. В добавок там MDI приложение, еще с форточками поковыряться надо время выделить. Инструментарий обработать.. ![]() |
Сообщ.
#4
,
|
|
|
Цитата Простые алгоритмы работы с изображением Цвета. Для написания хорошего графического редактора, необходимо добавить такую простую функцию, как фильтр. Он позволяет изменить какие-то свойства изображения. Давайте посмотрим, какие фильтры можно применить к цветам картинки. Первым делом нам необходимо получить массив пикселей, для дальнейшей работы с ними. Так как цветовые фильтры требуют работы с каждым отдельным пикселем, в нашем коде будет использоваться цикл, перебирающий пиксели и пременяющий фильтр: Подготовочные действия Цикл перебора по X, Y Применение формулы Конец цикла и заключительные действия Итак: подготовительные действия ![]() ![]() Byte* ptr; //Это объявление необходимо только для первого способа перебора Image->PixelFormat = pf24bit; // Наиболее оптимальный формат пикселей для наших фильтров StatusBar1->SimpleText = "Подождите пожалуйста"; В VCL существует два варианта циклов перебора: ![]() ![]() for(int y = 0; y < Image->Height; y++){ //Перебор строк ptr = (Byte*)Image->ScanLine[y]; //Получение текущей строки пикселей for (int x = 0; x < Image->Width * 3; x+=1) { //Перебор каждого пикселя из строки //RGB: ptr[x] = ... //Красный ptr[x+1] = ... //Зеленый ptr[x+2] = ... //Синий } Этот способ достаточно быстрый, однако, при его использовании могут возникать некоторые проблемы. Второй способ проще для понимания: ![]() ![]() for(int y = 0; y < Image->Height; y++){ //Перебор строк for (int x = 0; x < Image->Width; x++) { //Перебор каждого пикселя из строки Image->Pixels[x][y] = ... //Красный + зеленый + синий } } Рассмотрим сначала затемнение о осветление пикселей. В системе цветов RGB черным является цвет 0,0,0, а белым 255,255,255. Таким образом, при затемнении, каждый канал пиксела стремиться к 0,0,0 способом декрементирования. Также, следует учитывать тот факт, что если канал имеет значение 0, Декрементировать его нет смысла. Вот итоговый алгоритм: ![]() ![]() for(int y = 0; y < Image->Height; y++){ ptr = (Byte*)Image->ScanLine[y]; for (int x = 0; x < Image->Width * 3; x++) { //Особое внимание на 3 бита на одну точку- Image->Canvas->Width * 3 if(ptr[x] > 10) ptr[x] = (Byte)(ptr[x] - 10); } } Полная версия алгоритма обладает одной интересной особенностью: по причине того, что над каждым каналом каждого пикселя совершается одно и тоже действие, полный цикл затемнения отличается от приведенного выше, однако, более оптимизированным считается код, выполняемый за меньшее число итераций. Вот оптимизированная версия алгоритма: ![]() ![]() for(int y = 0; y < Image->Height; y++){ ptr = (Byte*)Image->ScanLine[y]; for (int x = 0; x < Image->Width * 3; x+=3) { //Особое внимание на 3 бита на одну точку- Image->Canvas->Width * 3 if(ptr[x] > 10 && ptr[x+1] > 10 && ptr[x+2] > 10) { ptr[x] = (Byte)(ptr[x] - 10); ptr[x+1] = (Byte)(ptr[x+1] - 10); ptr[x+2] = (Byte)(ptr[x+2] - 10); } } } Аналогичен код осветления: ![]() ![]() for(int y = 0; y < Image->Height; y++){ ptr = (Byte*)Image->ScanLine[y]; for (int x = 0; x < Image->Width * 3; x+=3) { //Особое внимание на 3 бита на одну точку- Image->Canvas->Width * 3 if(ptr[x] < 245 && ptr[x+1] < 245 && ptr[x+2] < 245) { ptr[x] = (Byte)(ptr[x] + 10); ptr[x+1] = (Byte)(ptr[x+1] + 10); ptr[x+2] = (Byte)(ptr[x+2] + 10); } } } Можно также привести изображение к определенному оттенку. Для этого необходимо изменить соотношение между каналами. Например, если вы хотите сделать так, чтобы каждый канал содержал только оттенки красного, надо рассчитать среднее значение между тремя каналами, а затем установить каналы G и B в 0, а R в полученное значение: ![]() ![]() int r = 0, g = 0, b = 0, color = 0; for(int y = 0; y < Image->Height; y++){ ptr = (Byte*)Image->ScanLine[y]; for (int x = 0; x < Image->Width * 3; x+=3) { r = ptr[x]; //Получаем g = ptr[x+1]; //значения b = ptr[x+2]; //каналов color = (r + g + b) / 3; //Выссчитываем среднее значение ptr[x] = 0; ptr[x+1] = 0; ptr[x+2] = color; } } Фильтрация "Оттенки серого" установливает значения всех каналов пикселя в одинаковые значения. Таким образом, все каналы уравновешены, и не добавляют в цвет пикселя "примеси". ![]() ![]() int r = 0, g = 0, b = 0, color = 0; for(int y = 0; y < Image->Height; y++){ ptr = (Byte*)Image->ScanLine[y]; for (int x = 0; x < Image->Width * 3; x+=3) { r = ptr[x]; //Получаем g = ptr[x+1]; //значения b = ptr[x+2]; //каналов color = (r + g + b) / 3; //Выссчитываем среднее значение ptr[x] = color; ptr[x+1] = color; ptr[x+2] = color; } } И, наконец, последний фильтр: "Инвертация цветов". ![]() ![]() for(int y = 0; y < Image->Height; y++){ ptr = (Byte*)Image->ScanLine[y]; for (int x = 0; x < Image->Width * 3; x+=3) { ptr[x] = (Byte)(256 - ptr[x]); ptr[x+1] = (Byte)(256 - ptr[x+1]); ptr[x+2] = (Byte)(256 - ptr[x+2]); } } Примечание: в данной статье представлены неоптимизированные версии алгоритмов. Наиболее узкими местами являются: использование промежуточных переменных и постоянное использование свойств Image->Width и Image->Height в цикле, для них рекомендуется исользовать промежуточные переменные, желательно типа register. Цитата Фильтра "Оттенки серого" установливает значения всех каналов пикселя в одинаковые значения. Почитай про конвертацию RGB->YUV и забудь про среднее арифметическое. Как Paint'е реализовано распыление и карандаш В OnMouseMove ![]() Распыление ![]() ![]() int x0, y0; for(float i=1;i<BrushRad; i++) { for(float f=1;f<360; f+=0.2) { if(rand()>16384) { x0 = X+cos(f)*i; y0 = Y+sin(f)*i; Image->Canvas->Pixels[x0][y0] = Image->Canvas->Brush->Color; } } } Карандаш ![]() ![]() Image->Canvas->Pen->Mode = pmCopy; Image->Canvas->LineTo(X, Y); |
Сообщ.
#5
,
|
|
|
Old, не надоело портянки не по делу развешивать? trosh'а в первую очередь интересует
-как загрузить картинку -как ее отмасштабировать -как что-то дорисовать -как что-то стереть -как восстановить предыдущую копию trosh, посмотри тут. Хоть и на Дельфях, но поможет. ЗЫ - мой первый пост в том топике просто проигнорируй, читай дальше. |
Сообщ.
#6
,
|
|
|
Цитата Coala @ Old, не надоело портянки не по делу развешивать? [b] Old, ты гений! ![]() У меня готов графический просмоторщик, там все читаемые файлы разбираются по расширениям, в итоге создается Bitmap, который и отображается в Image. |
Сообщ.
#7
,
|
|
|
Цитата Coala @ Old, не надоело портянки не по делу развешивать? trosh'а в первую очередь интересует Злая ты сегодня какая-то, коала \m/ -как загрузить картинку хотя бы так: ![]() ![]() Picture.LoadFromFile Image1.Picture.Assign(Clipboard) -как ее отмасштабировать ![]() ![]() //да, Coala, Ваш любимый ОР var B,L: TBitmap; R: TRect; begin L:=TBitmap.Create;// create source bitmap L.Assign(TBitmap(Image1.Picture));//get bitmap from picture B:=TBitmap.Create; // create buffer B.Width:=200; //new width B.Height:=100; //new height R.Left:=0; R.Top:=0; R.Right:=B.Width-1; R.Bottom:=B.Heigh-1; B.Canvas.StretchDraw(R,L);//redraw buffer from source Image1.Picture:=TPicture(B);//set new bitmap to the picture B.Free;//destroy resources L.Free;//destroy resources end; -как что-то дорисовать ![]() ![]() DrawFocusRect -как что-то стереть ![]() ![]() CreateRegion -как восстановить предыдущую копию сохранить - потом восстановить, типа, да? |
Сообщ.
#8
,
|
|
|
Цитата Old @ как восстановить предыдущую копию сохранить - потом восстановить, типа, да? Можно массив указателей завести, скажем из пяти, и по мере изменения Bitmap, добавлять новый и убивать самый старый. Можно все это не в памяти хранить.... ![]() |
Сообщ.
#9
,
|
|
|
а кто против-то...
|
Сообщ.
#10
,
|
|
|
Никто не против..
![]() В выходные буду делать. |
Сообщ.
#11
,
|
|
|
удачи
|
Сообщ.
#12
,
|
|
|
Цитата Old @ К тому же это старый Мяутовский текст, содержащий неверные алгоритмы обработки(например, оттенки серого считаются вовсе не так), который(текст) где-то здесь болтается. Так что достаточно было бы дать ссылку. Злая ты сегодня какая-то, коала \m/ |
Сообщ.
#13
,
|
|
|
trainer, orb его переработал: http://www.sources.ru/magazine/0805/paint.html
![]() |
Сообщ.
#14
,
|
|
|
Цитата trainer @ Цитата Old @ К тому же это старый Мяутовский текст, содержащий неверные алгоритмы обработки(например, оттенки серого считаются вовсе не так), который(текст) где-то здесь болтается. Так что достаточно было бы дать ссылку.Злая ты сегодня какая-то, коала \m/ Не помню я ссылок, сохраненные когда-то страницы с Исходников лежат кучей где-то... Мне проще копи-пейстом... А это: PS: Этот вопрос неоднократно поднимался на форуме. Вверху страницы есть кнопка ПОИСК мне надоело вставлять - ленивых здесь море, все равно будут упорно не обращать на этот совет внимания. |
Сообщ.
#15
,
|
|
|
Old
Самое гдавное в посте trainer'а, конечно же предпочел не заметить ![]() Цитата trainer К тому же это старый Мяутовский текст, содержащий неверные алгоритмы обработки(например, оттенки серого считаются вовсе не так), который(текст) где-то здесь болтается. Так что достаточно было бы дать ссылку. |