21

ある色を同じ色の別の色合いに補間しようとしています。(例: スカイブルーからダークブルーへ、そして戻る)。

範囲が 0 ~ 255 または 0 ~ 1 の場合に使用できるコードを見つけました。ただし、私の場合、Color1 と Color2 の RGB コードがあり、回転を発生させたいと考えています。

カラー 1: 151,206,255
カラー 2: 114,127,157

これについてどうすればいいですか?

4

7 に答える 7

34

これが少し古いことは知っていますが、誰かがそれを探しているなら価値があります.

まず第一に、RGB を含む任意の色空間で補間を行うことができます。これは、私の意見では、最も簡単な色空間の 1 つです。

バリエーションが 0 から 1 の間の分数値 (たとえば 0.3) によって制御されると仮定しましょう。ここで、0 はフル カラー 1 を意味し、1 はフル カラー 2 を意味します。

法則:

Result = (color2 - color1) * fraction + color1

申請中:

RGB には 3 つのチャネル (赤、緑、青) があるため、チャネルごとにこの計算を実行する必要があります。

あなたの例の色を使用して:

fraction: 0.3
color1: 151,206,255
color2: 114,127,157

R =  (114-151) * fraction + 151
G =  (127-206) * fraction + 206
B =  (157-255) * fraction + 255

C/C++ でのコード例:

/**
 * interpolate 2 RGB colors
 * @param color1    integer containing color as 0x00RRGGBB
 * @param color2    integer containing color as 0x00RRGGBB
 * @param fraction  how much interpolation (0..1)
 * - 0: full color 1
 * - 1: full color 2
 * @return the new color after interpolation
 */
int interpolate(int color1, int color2, float fraction)
{
        unsigned char   r1 = (color1 >> 16) & 0xff;
        unsigned char   r2 = (color2 >> 16) & 0xff;
        unsigned char   g1 = (color1 >> 8) & 0xff;
        unsigned char   g2 = (color2 >> 8) & 0xff;
        unsigned char   b1 = color1 & 0xff;
        unsigned char   b2 = color2 & 0xff;

        return (int) ((r2 - r1) * fraction + r1) << 16 |
                (int) ((g2 - g1) * fraction + g1) << 8 |
                (int) ((b2 - b1) * fraction + b1);
}

/* 
 * 0x0097ceff == RGB(151,206,255)
 * 0x00727f9d == RGB(114,127,157)
 */
int new_color = interpolate(0x0097ceff, 0x00727f9d, 0.3f);
于 2014-01-09T02:05:38.057 に答える
20

RGB を HSV に変換し、そのコンポーネントを調整してから、RGB に戻すことをお勧めします。

ウィキペディアにはそれに関する記事があり、以前にここで議論されています。

HSL から RGB への色変換

RGB を HSV に変換するアルゴリズムと HSV を RGB に変換するアルゴリズム (両方とも 0 ~ 255 の範囲)

また、多くのフレームワークには変換機能があります。たとえば、Qt にはQColor クラスがあります。


しかし、問題は実際の補間に関するものでした...ここに簡単な補間関数があります:

// 0 <= stepNumber <= lastStepNumber
int interpolate(int startValue, int endValue, int stepNumber, int lastStepNumber)
{
    return (endValue - startValue) * stepNumber / lastStepNumber + startValue;
}

したがって、ループ内で、補間するすべての色コンポーネントに対してそれを呼び出します。RBG 補間では、すべてのコンポーネントを補間する必要があります。他の色空間では、1 つだけ補間する必要がある場合があります。

于 2012-11-21T08:24:03.977 に答える
11

RGBカラーをHSVに変換し、各コンポーネントを補間します(色だけでなく、回答の最後を参照)。その後、RGBに戻すことができます。

RGB 補間を実行できますが、HSV では色が輝度と彩度から分離されているため、結果は HSV の方が優れています ( HSV に関するウィキペディアの記事)。HSV 補間は、RGB 補間よりも「論理的」です。RGB 補間では、補間中に余分な色を取得できるからです。

補間のためのいくつかのコード:

template<typename F>
ColorRGB interpolate(ColorRGB a, ColorRGB b, float t, F interpolator)
{
    // 0.0 <= t <= 1.0
    ColorHSV ca = convertRGB2HSV(a);
    ColorHSV cb = convertRGB2HSV(b);
    ColorHSV final;

    final.h = interpolator(ca.h, cb.h, t);
    final.s = interpolator(ca.s, cb.s, t);
    final.v = interpolator(ca.v, cb.v, t);

    return convertHSV2RGB(final);
}

int linear(int a, int b, float t)
{
    return a * (1 - t) + b * t;
}

// use: result = interpolate(color1,color2,ratio,&linear);
于 2012-11-21T08:22:51.750 に答える
0

この質問に「openframeworks」タグを付けたようです。したがって、メソッドを使用するofColor::getLerpedか、ofColor::lerp

getLerpedlerp色を変更しながら、新しい値を返します。

例えば:

ofColor c1(151,206,255);
ofColor c2(114,127,157);


float p = 0.2f;
ofColor c3 = c1.getLerped(c2, p);

また

c1.lerp(c2, 0.3f);
于 2012-12-19T23:29:47.547 に答える
0

Synxis の C の例(上記) を実行可能な JavaScript プログラムに適合させました。

プログラムは、赤から黄色を補間します。入力と出力はRGB 空間にありますが、補間はHSV 空間で処理されます。RGB 補間の例も追加しました。以下に示すように、RGB 空間緑を補間すると、濃い黄色が生成されます。

/** Main */
var red        = { r : 255, g : 0,   b : 0 };
var green      = { r : 0,   g : 255, b : 0 };
var yellow     = interpolateHsv(red, green, 0.5, linear);
var darkYellow = interpolateRgb(red, green, 0.5, linear);

document.body.innerHTML =
  'Yellow: '      + JSON.stringify(yellow,     null, '  ') + '<br />' +
  'Dark Yellow: ' + JSON.stringify(darkYellow, null, '  ');

/**
 * Returns an HSV interpolated value between two rgb values. 
 *
 * @param {Object} rgbA - rgb() tuple
 * @param {Object} rgbB - rgb() tuple
 * @param {Number} threshold - float between [0.0, 1.0]
 * @param {function} interpolatorFn - interpolator function
 * @return {Object} rbg
 */
function interpolateHsv(rgbA, rgbB, threshold, interpolatorFn) {
  var hsvA = rgbToHsv(rgbA);
  var hsvB = rgbToHsv(rgbB);
  threshold = toArray(threshold, 3);
  return hsvToRgb({
    h : interpolatorFn(hsvA.h, hsvB.h, threshold[0]),
    s : interpolatorFn(hsvA.s, hsvB.s, threshold[1]),
    v : interpolatorFn(hsvA.v, hsvB.v, threshold[2])
  });
}

/**
 * Returns an RGB interpolated value between two rgb values. 
 *
 * @param {Object} rgbA - rgb() tuple
 * @param {Object} rgbB - rgb() tuple
 * @param {Number} threshold - float between [0.0, 1.0]
 * @param {function} interpolatorFn - interpolator function
 * @return {Object} rbg
 */
function interpolateRgb(rgbA, rgbB, threshold, interpolatorFn) {        
  threshold = toArray(threshold, 3);
  return {
    r : ~~interpolatorFn(rgbA.r, rgbB.r, threshold[0]),
    g : ~~interpolatorFn(rgbA.g, rgbB.g, threshold[1]),
    b : ~~interpolatorFn(rgbA.b, rgbB.b, threshold[2])
  };
}

/**
 * Returns an interpolated value between two values. 
 *
 * @param {Number} valueA - color channel int value
 * @param {Number} valueB - color channel int value
 * @param {Number} threshold - float between [0.0, 1.0]
 * @param {function} interpolatorFn - interpolator function
 * @return {int}
 */
function linear(valueA, valueB, threshold) {
  return valueA * (1 - threshold) + valueB * threshold;
}

/**
 * Converts an RGB color value to HSV. Conversion formula
 * adapted from http://en.wikipedia.org/wiki/HSV_color_space.
 * Assumes r, g, and b are contained in the set [0, 255] and
 * returns h, s, and v in the set [0, 1].
 *
 * @param {Object} rgb - Color in rgb mode
 * @return {Object} - Color in hsv mode
 */
function rgbToHsv(rgb) {
  var r = rgb.r / 255,
      g = rgb.g / 255,
      b = rgb.b / 255;
  var max = Math.max(r, g, b), min = Math.min(r, g, b);
  var h, s, v = max;
  var d = max - min;
  s = max === 0 ? 0 : d / max;
  if (max == min) {
    h = 0; // achromatic
  } else {
    switch(max) {
      case r: h = (g - b) / d + (g < b ? 6 : 0); break;
      case g: h = (b - r) / d + 2; break;
      case b: h = (r - g) / d + 4; break;
    }
    h /= 6;
  }
  return {
    h : h,
    s : s,
    v : v
  };
}

/**
 * Converts an HSV color value to RGB. Conversion formula
 * adapted from http://en.wikipedia.org/wiki/HSV_color_space.
 * Assumes h, s, and v are contained in the set [0, 1] and
 * returns r, g, and b in the set [0, 255].
 *
 * @param {Object} hsv - Color in hsv mode
 * @return {Object} - Color in rgb mode
 */
function hsvToRgb(hsv){
  var r, g, b, i, f, p, q, t,
      h = hsv.h,
      s = hsv.s,
      v = hsv.v;
  i = Math.floor(h * 6);
  f = h * 6 - i;
  p = v * (1 - s);
  q = v * (1 - f * s);
  t = v * (1 - (1 - f) * s);
  switch(i % 6){
    case 0: r = v, g = t, b = p; break;
    case 1: r = q, g = v, b = p; break;
    case 2: r = p, g = v, b = t; break;
    case 3: r = p, g = q, b = v; break;
    case 4: r = t, g = p, b = v; break;
    case 5: r = v, g = p, b = q; break;
  }
  return {
    r : r * 255,
    g : g * 255,
    b : b * 255
  };
}

function isNumeric(n) {
  return !isNaN(parseFloat(n)) && isFinite(n);
}

function toArray(arr, size) {
  var isNum = isNumeric(arr);
  arr = !Array.isArray(arr) ? [arr] : arr;
  for (var i = 1; i < size; i++) {
    if (arr.length < size) {
      arr.push(isNum ? arr[0] : 0);
    }
  }
  return arr;
}

于 2015-04-24T15:42:25.953 に答える