Градиент
| |
Alkosha | Дата: Суббота, 21 Июня 2014, 20:00 | Сообщение # 1 |
участник
Сейчас нет на сайте
| Допустим, на вход функции поступают параметры для цветовых переходов от одного цвета до другого.
Вот к примеру color1={r1,g1,b1}; color2={r2,g2,b2} тут цикл for=0 to len // где len - ширина градиента. затем линиями line(x1,y1,x2,y2) с цветовыми переходами от color1 до color2. Как определить для каждого шага в цикле цвет перехода?
Сообщение отредактировал Alkosha - Суббота, 21 Июня 2014, 20:01 |
|
| |
wcpt | Дата: Понедельник, 23 Июня 2014, 20:28 | Сообщение # 2 |
постоянный участник
Сейчас нет на сайте
| может, глупо и наивно, но ты не пробовал найти разницу между соответственными компонентами цвета, поделить эти разницы на число шагов, и прибавлять эти разницы к компонентам исходного цвета в цикле? Я не пробовал, просто предположил, вдруг это оно
Сообщение отредактировал wcpt - Понедельник, 23 Июня 2014, 20:30 |
|
| |
daun | Дата: Понедельник, 23 Июня 2014, 20:42 | Сообщение # 3 |
постоянный участник
Сейчас нет на сайте
| попробуй среднее арифметическое (или как там его Код color3=RGB( (r1*shag+r2) div shag+1, (g1*shag+g2) div shag+1, (b1*shag+b2) div shag+1,)
|
|
| |
wcpt | Дата: Вторник, 24 Июня 2014, 11:50 | Сообщение # 4 |
постоянный участник
Сейчас нет на сайте
| Автор, ты чего? Пробовал что-либо делать? Посмотри-ка на это (гипотетический си-подобный язык): Код int stepnum = 100 //влияет на число оттенков int width = 100 //ширина полоски int height = 100 // высота полоски void Grad (color clr1,color clr2) { int dr = clr2.R-clr1.R; int dg = clr2.G-clr1.G; int db = clr2.B-clr1.B;
dr /= stepnum; dg /= stepnum; db /= stepnum;
for (int i=0; i<width;i++) { color _clr = RGB(clr1.R+dr,clr1.G+dg,clr1.B+db) for (int j=0; j<height; j++) { image.putpixel(i,j,_clr) } } }
Сообщение отредактировал wcpt - Вторник, 24 Июня 2014, 12:14 |
|
| |
Alkosha | Дата: Суббота, 05 Июля 2014, 08:08 | Сообщение # 5 |
участник
Сейчас нет на сайте
| Но тут же в теле цикла не происходит никакого изменения _clr остаётся постоянным. Код color _clr = RGB(clr1.R+dr,clr1.G+dg,clr1.B+db)
Вот например сие даёт сплошной ярко-красный цвет.
Код SDL_Color skyColorTop={255,100,100,255}; SDL_Color skyColorBottom={255,10,10,255};
int dr = skyColorBottom.r-skyColorTop.r; int dg = skyColorBottom.g-skyColorTop.g; int db = skyColorBottom.b-skyColorTop.b; dr /= stepnum; dg /= stepnum; db /= stepnum;
for(int a=0;a<600;a+=1) { SDL_SetRenderDrawColor(renderer, skyColorBottom.r+dr,skyColorBottom.g+dg, skyColorBottom.b+db, 255); SDL_RenderDrawLine(renderer,0,a,800,a); }
Сообщение отредактировал Alkosha - Суббота, 05 Июля 2014, 08:09 |
|
| |
daun | Дата: Суббота, 05 Июля 2014, 11:05 | Сообщение # 6 |
постоянный участник
Сейчас нет на сайте
| 1) байт - целое от 0 до 255, выход за пределы ни к чему хорошему не приведет 2) rgb кодируется тремя байтами, на каждый по одному, плюс четвертый альфа (если 32 бита, возможны варианты) 3) если r,g,b по значению близки друг к другу - теряется цвет, пиксель стремится к черно-белому, и наоборот 4) величина дает яркость, 0 - темный, 255 - светлый 5) смешивание двух цветов определяется по средней - (r1+r2)/2 (g1+g2)/2 (b1+b2)/2 6) манипуляции с цветом (в фильтрах например) только с использованием процентов (гарантирует значение в пределах байта) r:=r+trunc((256-r)/100*10); g:=g+trunc((256-g)/100*10); b:=b+trunc((256-b)/100*10);
Код procedure GraG(bit:TBitMap; col1:TColor; col2:TColor); var a:integer; r1,g1,b1,r2,g2,b2:byte; begin r1:=GetRValue(col1); g1:=GetGValue(col1); b1:=GetBValue(col1); r2:=GetRValue(col2); g2:=GetGValue(col2); b2:=GetBValue(col2); for a:=0 to bit.Width-1 do begin bit.Canvas.Pen.Color:=RGB(trunc(r1-(r1-r2)/(bit.Width-1)*a), trunc(g1-(g1-g2)/(bit.Width-1)*a), trunc(b1-(b1-b2)/(bit.Width-1)*a)); bit.Canvas.MoveTo(a,0); bit.Canvas.LineTo(a,bit.Height); end; end;
|
|
| |
wcpt | Дата: Суббота, 05 Июля 2014, 12:02 | Сообщение # 7 |
постоянный участник
Сейчас нет на сайте
| не знаю, если честно, почему у тебя не получается. Я привел частный случай. Его еще нужно подстроить под необходимую длину градиента, которая тут взята для примера. Плюс, при слишком малой ширине весь спектр не будет умещаться в полоску, это тоже надо учесть.
Добавлено (05.07.2014, 11:22) --------------------------------------------- Цитата Alkosha ( ) Но тут же в теле цикла не происходит никакого изменения я привел пример поточечного заполнения, без линий, учти. И, на всякий случай, clr1 - цвет левой части полоски, clr2 - правой части.
Добавлено (05.07.2014, 11:57) --------------------------------------------- вот и я. Кое-какие условности были убраны, и теперь все в норме: Код const int height = 100; const int width = 200; float _dr; float _db; float _dg; float __dr; float __db; float __dg;
void Grad(color clr1,color clr2) { _dr = (clr2.R - clr1.R); _dg = (clr2.G - clr1.G); _db = (clr2.B - clr1.B);
_dr /= width; _dg /= width; _db /= width;
color clr_;
for (int i = 0; i < width; i++) { __dr += _dr; __dg += _dg; __db += _db;
clr_ = RGB(clr1.R + (int)__dr, clr1.G + (int)__dg, clr1.B + (int)__db);
for (int j = 0; j < height; j++) { image.putpixel(i, j, clr_); } } }
Добавлено (05.07.2014, 12:02) --------------------------------------------- ну и конечно, если захочется линиями, то внутренний цикл убирай, ставь вместо него что-то типа line(i,0,i,height,clr_), если полоска градиента расположена в левом верхнем углу.
Сообщение отредактировал wcpt - Суббота, 05 Июля 2014, 13:52 |
|
| |
Alkosha | Дата: Воскресенье, 06 Июля 2014, 00:58 | Сообщение # 8 |
участник
Сейчас нет на сайте
| Цитата ну и конечно, если захочется линиями, то внутренний цикл убирай, ставь вместо него что-то типа line(i,0,i,height,clr_), если полоска градиента расположена в левом верхнем углу.
это и так понятно. Просто в Вашем первом варианте в теле цикла (не там где происходит попиксельное рисование линий), переменная остаётся без изменений. Код for (int i=0; i<width;i++) { color _clr = RGB(clr1.R+dr,clr1.G+dg,clr1.B+db) /* для наглядности закомментируем
for (int j=0; j<height; j++) { image.putpixel(i,j,_clr) } */ }
А что касается Вашего последнего варианта, то даже не знаю, чё я делаю не так. Градиента никакого. Сплошной цвет получается Структура SDL_Color'a - r,g,b,a
Код SDL_Color skyColorTop={255,0,0,0}; SDL_Color skyColorBottom={0,0,255,255};
SDL_RenderSetScale(renderer,1,1); SDL_SetRenderDrawBlendMode( renderer, SDL_BLENDMODE_BLEND);
float _dr; float _db; float _dg; float __dr; float __db; float __dg;
_dr = skyColorBottom.r-skyColorTop.r; _dg = skyColorBottom.g-skyColorTop.g; _db = skyColorBottom.b-skyColorTop.b;
_dr /= 600; _dg /= 600; _db /= 600;
for(int a=0;a<600;a+=1) { __dr += _dr; __dg += _dg; __db += _db;
SDL_SetRenderDrawColor(renderer, skyColorTop.r + (int)__dr, skyColorTop.g + (int)__dg, skyColorTop.b + (int)__db, 255); SDL_RenderDrawLine(renderer,0,a,800,a);
} }
рисует сплошняком цветом skyColorTop (он же clr1). Как будто к нему прибавляются нули по rgb-каналам.
И даже если бы и прибавлялось что-то, ведь тут вполне возможно переполнение за значение 255 (допустим clr1.r=250, то в установке цвета к нему ещё бы прибавилось сего-нибудь (допустим единицу), то есть он бы резко спал в значение 0)
Сообщение отредактировал Alkosha - Воскресенье, 06 Июля 2014, 00:59 |
|
| |
wcpt | Дата: Воскресенье, 06 Июля 2014, 13:23 | Сообщение # 9 |
постоянный участник
Сейчас нет на сайте
| Цитата Alkosha ( ) это и так понятно. Просто в Вашем первом варианте в теле цикла (не там где происходит попиксельное рисование линий), переменная остаётся без изменений. это где же? Код color _clr = RGB(clr1.R+dr,clr1.G+dg,clr1.B+db) тут, что ли? Да, ошибочка, извиняюсь. Тут, по идее должно вместо _clr быть использовано clr1.
могу предположить, что проблемы возникают из-за приведения типов. Как я посмотрел, у SDL_Color r g b задаются как uint8. Ты же __dr __dg __db к int приводишь. Ну а потом они автоматом к uint8 приводятся, если ты пробовал именно тот код, что привел здесь. Не помню всех подробностей, поэтому могу ошибаться. В моем примере я предполагал, что r g b как int задаются. Ну, и конечно, _dr, _dg, _db, __dr, __dg, __db могут быть и отрицательными.
Добавлено (06.07.2014, 13:23) --------------------------------------------- Ну и еще одна деталь - Код SDL_Color skyColorTop={255,0,0,0}; SDL_Color skyColorBottom={0,0,255,255}; случаем не красный и синий соответственно? Так вот, проблем нет и с ними.
а переполнения быть не может, ведь шаг прибавления _dx постоянен и представлен в пространстве в пределах байта. При том условии, конечно,что при касте к int число округляется до предыдущего целого.
Сообщение отредактировал wcpt - Воскресенье, 06 Июля 2014, 15:50 |
|
| |
Alkosha | Дата: Воскресенье, 06 Июля 2014, 15:54 | Сообщение # 10 |
участник
Сейчас нет на сайте
| Даже когда создал структуру, результат всё тот же - сплошной цвет, который указан в skyColorTop (он же clr1 ) Код struct mycolor { int r; int g; int b; } ;
|
|
| |
wcpt | Дата: Воскресенье, 06 Июля 2014, 15:57 | Сообщение # 11 |
постоянный участник
Сейчас нет на сайте
| покажи полностью, как используешь, погляжу.
|
|
| |
Alkosha | Дата: Воскресенье, 06 Июля 2014, 16:31 | Сообщение # 12 |
участник
Сейчас нет на сайте
| Код struct mycolor { int r; int g; int b; } ;
public: void sky() {
mycolor skyColorTop={255,0,0}; mycolor skyColorBottom={0,0,255};
float _dr; float _db; float _dg; float __dr; float __db; float __dg;
_dr = skyColorBottom.r-skyColorTop.r; _dg = skyColorBottom.g-skyColorTop.g; _db = skyColorBottom.b-skyColorTop.b;
_dr /= 600; _dg /= 600; _db /= 600;
for(int a=0;a<600;a+=1) { __dr += _dr; __dg += _dg; __db += _db;
SDL_SetRenderDrawColor(renderer, skyColorTop.r +(int) __dr, skyColorTop.g +(int) __dg, skyColorTop.b +(int) __db, 255); SDL_RenderDrawLine(renderer,0,a,800,a);
} }
|
|
| |
wcpt | Дата: Воскресенье, 06 Июля 2014, 16:39 | Сообщение # 13 |
постоянный участник
Сейчас нет на сайте
| я написал, что проблемы, вероятно, из-за того, что у SDL_Color r g b a задаются как uint8, т.е. как беззнаковые числа. То есть, Код skyColorTop.r +(int) __dr должно быть беззнаковым.
А в свою очередь, есть число со знаком, т.е. оно должно быть скастовано в беззнаковое число, по сути. Однако что случится, если (int)__dr - отрицательное? Это вполне возможно, а учитывая конкретные цвета - гарантировано. Каким оно будет после приведения, можешь сказать?
Сообщение отредактировал wcpt - Воскресенье, 06 Июля 2014, 16:49 |
|
| |
Alkosha | Дата: Воскресенье, 06 Июля 2014, 16:53 | Сообщение # 14 |
участник
Сейчас нет на сайте
| Цитата wcpt ( ) я написал, что проблемы, вероятно, из-за того, что у SDL_Color r g b a задаются как uint8, т.е. как беззнаковые числа. То есть,
В приведённом мною листинге уже нет SDL_Color .
Тут же своя структура с интами Код struct mycolor { int r; int g; int b; } ;
Добавлено (06.07.2014, 16:53) --------------------------------------------- То есть тут -- int + int Код skyColorTop.r +(int) __dr
Сообщение отредактировал Alkosha - Воскресенье, 06 Июля 2014, 16:54 |
|
| |
wcpt | Дата: Воскресенье, 06 Июля 2014, 17:19 | Сообщение # 15 |
постоянный участник
Сейчас нет на сайте
| хорошо, но это, все же, должно смутить, как минимум: https://wiki.libsdl.org/SDL_SetRenderDrawColor
Код int SDL_SetRenderDrawColor(SDL_Renderer* renderer, Uint8 r, Uint8 g, Uint8 b, Uint8 a) т.е. в этой функции тоже uint8.
Сообщение отредактировал wcpt - Воскресенье, 06 Июля 2014, 17:21 |
|
| |
Alkosha | Дата: Воскресенье, 06 Июля 2014, 17:24 | Сообщение # 16 |
участник
Сейчас нет на сайте
| Даже если и так, я пробовал так же (Uint8) __dr , ещё когда skyColorTop был SDL_Color'ом. Тот же результат
|
|
| |
wcpt | Дата: Воскресенье, 06 Июля 2014, 17:26 | Сообщение # 17 |
постоянный участник
Сейчас нет на сайте
| а это Цитата Alkosha ( ) (Uint8) __dr и не поможет. Если __dr отрицательное, то как оно может быть корректно представлено в uint8? Я пытаюсь тебя подвести к тому, что сначала надо произвести вычисления с "удобными" типами, а потом результаты (которые, по идее, будут в пределах байта, почему я уже написал) привести к uint8. Ну и вызывать функцию с приведенными к uint8 результатами.
Сообщение отредактировал wcpt - Воскресенье, 06 Июля 2014, 17:34 |
|
| |
Alkosha | Дата: Воскресенье, 06 Июля 2014, 19:20 | Сообщение # 18 |
участник
Сейчас нет на сайте
| Цитата wcpt ( ) а потом результаты (которые, по идее, будут в пределах байта, почему я уже написал)
не важно, будет там инт или байт, так как там интенсивность возрастает от 0 до 255-ти, затем от 256 до 511-ти и так далее. так же с минусовым знаком.
Я к тому, что while(!0) { SDL_Color rgb; rgb++; render(); }
Будет постоянно мигать (постепенно возрастать яркость , затем резко гаснуть, и опять постепенно возрастать по яркости).
|
|
| |
wcpt | Дата: Воскресенье, 06 Июля 2014, 22:10 | Сообщение # 19 |
постоянный участник
Сейчас нет на сайте
| Автор, ты вместо того, чтобы спорить, попробовал бы сделать так, как я сказал. Специально для тебя скачал эсдиэл ту поинт зироу, установил, глянул уроки для начинающих, и попробовал эту штуку. А для чего? Чтобы удостовериться, что я был прав c самого начала, и что оно само автоматом все прекрасно приводится? Вот код, полностью, работает, вроде(и без всяких приведений!):
Код int _tmain(int argc, _TCHAR* argv[]) { if (SDL_Init(SDL_INIT_EVERYTHING) != 0){ std::cout << "SDL_Init Error: " << SDL_GetError() << std::endl; return 1; }
SDL_Window *win = SDL_CreateWindow("Hello World!", 100, 100, 640, 480, SDL_WINDOW_SHOWN);
if (win == nullptr){ std::cout << "SDL_CreateWindow Error: " << SDL_GetError() << std::endl; return 1; }
SDL_Renderer *ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); if (ren == nullptr){ SDL_DestroyWindow(win); std::cout << "SDL_CreateRenderer Error: " << SDL_GetError() << std::endl; SDL_Quit(); }
SDL_Color clr1 = { 255, 0, 0, 255 }; SDL_Color clr2 = { 0, 0, 255, 255 };
float _dr = clr2.r - clr1.r; float _dg = clr2.g - clr1.g; float _db = clr2.b - clr1.b;
float __dr = 0; float __db = 0; float __dg = 0;
_dr /= 600; _dg /= 600; _db /= 600;
for (int i = 0; i < 600; i++) {
__dr += _dr; __dg += _dg; __db += _db;
SDL_SetRenderDrawColor(ren, clr1.r + __dr, clr1.g + __dg, clr1.b + __db, 255);
SDL_RenderDrawLine(ren, 0, i, 800, i); }
SDL_RenderPresent(ren);
SDL_Delay(2000);
SDL_DestroyRenderer(ren); SDL_DestroyWindow(win); SDL_Quit();
_getch();
return 0; }
Сообщение отредактировал wcpt - Воскресенье, 06 Июля 2014, 22:42 |
|
| |
Alkosha | Дата: Понедельник, 07 Июля 2014, 00:03 | Сообщение # 20 |
участник
Сейчас нет на сайте
| странно... так работает. Но не вижу где разница с моим листингом (за исключением названий переменных)...
|
|
| |
|