В настоящее время я пытаюсь создать класс градиента цвета для моего исследователя Mandelbrot Set.Линейный градиент цвета не работает
Он считывает цветовые ограничения (RGBA8888
цвет и положение между 0 и 1) из текстового файла и добавляет их к вектору, который используется для определения цветов в определенной позиции.
Чтобы вычислить цвет, алгоритм выполняет поиск следующего ограничения с обеих сторон от заданной позиции, разбивает цвет на четыре отдельных канала, а затем для каждого из них выполняет поиск по нижнему из них и добавляет часть разница равна отношению (x-lpos)/(upos-lpos)
к нижнему цвету. После этого каналы сдвигаются и ORed вместе, а затем возвращаются как RGBA8888
беззнаковое целое число. (См код ниже.)
EDIT: более или менее я полностью переписал класс градиента, фиксируя некоторые проблемы и делает его более удобным для чтения для отладки (Это становится медленным, как ад, хотя, но -Os
принимает забота об этом). Однако, это все еще не так, как должно быть.
class Gradient { //remade, Some irrelevant methods and de-/constructors removed
private:
map<double, unsigned int> constraints;
public:
unsigned int operator[](double value) {
//Forbid out-of-range values, return black
if (value < 0 || value > 1+1E-10) return 0xff;
//Find upper and lower constraint
auto upperC = constraints.lower_bound(value);
if (upperC == constraints.end()) upperC = constraints.begin();
auto lowerC = upperC == constraints.begin() ? prev(constraints.end(), 1) : prev(upperC, 1);
if (value == lowerC->first) return lowerC->second;
double lpos = lowerC->first;
double upos = upperC->first;
if (upos < lpos) upos += 1;
//lower color channels
unsigned char lred = (lowerC->second >> 24) & 0xff;
unsigned char lgreen = (lowerC->second >> 16) & 0xff;
unsigned char lblue = (lowerC->second >> 8) & 0xff;
unsigned char lalpha = lowerC->second & 0xff;
//upper color channels
unsigned char ured = (upperC->second >> 24) & 0xff;
unsigned char ugreen = (upperC->second >> 16) & 0xff;
unsigned char ublue = (upperC->second >> 8) & 0xff;
unsigned char ualpha = upperC->second & 0xff;
unsigned char red = 0, green = 0, blue = 0, alpha = 0xff;
//Compute each channel using
// lower color + dist(lower, x)/dist(lower, upper) * diff(lower color, upper color)
if (lred < ured)
red = lred + (value - lpos)/(upos - lpos) * (ured - lred);
else red = ured + (upos - value)/(upos - lpos) * (ured - lred);
if (lgreen < ugreen)
green = lgreen + (value - lpos)/(upos - lpos) * (ugreen - green);
else green = ugreen + (upos - value)/(upos - lpos) * (ugreen - lgreen);
if (lblue < ublue)
blue = lblue + (value - lpos)/(upos - lpos) * (ublue - lblue);
else blue = ublue + (upos - value)/(upos - lpos) * (ublue - lblue);
if (lalpha < ualpha)
alpha = lalpha + (value - lpos)/(upos - lpos) * (ualpha - lalpha);
else alpha = ualpha + (upos - value)/(upos - lpos) * (ualpha - lalpha);
//Merge channels together and return
return (red << 24) | (green << 16) | (blue << 8) | alpha;
}
void addConstraint(unsigned int color, double position) {
constraints[position] = color;
}
};
Использование в методе обновления:
image[r + rres*i] = grd[ratio];
//With image being a vector<unsigned int>, which is then used as data source for a `SDL_Texture` using `SDL_UpdateTexture`
Он работает только частично, хотя. Когда я только использовать черный/белый градиент, результирующее изображение по назначению:
Градиент файла:
2
0 000000ff
1 ffffffff
Однако, когда я использовать более красочный градиент (линейный вариант Ultra Fractal gradient, входной файл ниже),
образ далек от желаемого результата
изображение все еще не показывает нужную окраску:
Gradient файл:
5
0 000764ff
.16 206bcbff
.42 edffffff
.6425 ffaa00ff
0.8575 000200ff
Что я делаю неправильно? Я переписал метод operator[]
несколько раз, без каких-либо изменений.
Вопросы для уточнения или общие замечания по моему коду приветствуются.
Вы действительно должны переместить много этого кода из 'operator []' и в метод, который читает ограничения. Используйте отсортированный «вектор» вместо «карты», чтобы удерживать ограничения, и разбирайте их на отдельные компоненты RGBA как можно раньше. – Alnitak
oh, и если вы сохраните свои компоненты RGBA в своем собственном классе, вы, вероятно, должны поместить метод, который выполняет основную математику в тех цветах внутри этого класса. – Alnitak
Почему карта должна быть проблемой? Я фактически использовал вектор раньше, но затем переключился на карту, потому что значения в карте ** сортируются ** по возрастанию ключа, что дает время логарифмического доступа при инициализации. – s3lph