كيف يمكنني تحديد متغير لون أغمق أو أفتح من لون معين؟

StackOverflow https://stackoverflow.com/questions/97646

  •  01-07-2019
  •  | 
  •  

سؤال

نظرًا للون المصدر لأي درجة لون بواسطة النظام أو المستخدم، أرغب في الحصول على خوارزمية بسيطة يمكنني استخدامها لتحديد متغيرات أفتح أو أغمق من اللون المحدد.يشبه التأثيرات المستخدمة في Windows Live Messenger لتصميم واجهة المستخدم.

اللغة هي C# مع .net 3.5.

الرد على التعليق: تنسيق اللون هو (ألفا)RGB.مع القيم بالبايت أو العوامات.

إجابة العلامة: بالنسبة لسياق استخدامي (بعض تأثيرات واجهة المستخدم البسيطة)، فإن الإجابة التي أضع عليها علامة مقبولة هي في الواقع الأكثر بساطة في هذا السياق.ومع ذلك، فقد تخليت عن التصويت للإجابات الأكثر تعقيدًا ودقة أيضًا.يجب على أي شخص يقوم بعمليات ألوان أكثر تقدمًا ويجد هذا الموضوع في المستقبل التحقق من ذلك بالتأكيد.شكرا علي العموم.:)

هل كانت مفيدة؟

المحلول

ما عليك سوى ضرب قيم RGB بالمبلغ الذي تريد تعديل المستوى به.إذا كان أحد الألوان عند القيمة القصوى بالفعل، فلن تتمكن من جعله أكثر سطوعًا (باستخدام حسابات HSV على أي حال).

وهذا يعطي نفس النتيجة تمامًا مع قدر أقل من العمليات الحسابية مثل التبديل إلى HSV ثم تعديل V.وهذا يعطي نفس نتيجة التبديل إلى HSL ثم تعديل L، طالما أنك لا تريد أن تبدأ في فقدان التشبع.

نصائح أخرى

في XNA هناك Color.Lerp طريقة ثابتة أن يفعل هذا كالفرق بين لونين.

Lerp هي عملية حسابية بين عائمتين تغير قيمة الأولى بنسبة الفرق بينهما.

إليك طريقة تمديد للقيام بذلك إلى ملف float:

public static float Lerp( this float start, float end, float amount)
{
    float difference = end - start;
    float adjusted = difference * amount;
    return start + adjusted;
}

إذن فإن عملية lerp البسيطة بين لونين باستخدام RGB ستكون:

public static Color Lerp(this Color colour, Color to, float amount)
{
    // start colours as lerp-able floats
    float sr = colour.R, sg = colour.G, sb = colour.B;

    // end colours as lerp-able floats
    float er = to.R, eg = to.G, eb = to.B;

    // lerp the colours to get the difference
    byte r = (byte) sr.Lerp(er, amount),
         g = (byte) sg.Lerp(eg, amount),
         b = (byte) sb.Lerp(eb, amount);

    // return the new colour
    return Color.FromArgb(r, g, b);
}

مثال على تطبيق ذلك سيكون مثل:

// make red 50% lighter:
Color.Red.Lerp( Color.White, 0.5f );

// make red 75% darker:
Color.Red.Lerp( Color.Black, 0.75f );

// make white 10% bluer:
Color.White.Lerp( Color.Blue, 0.1f );

HSV ( Hue / Saturation / Value ) يسمى أيضًا HSL ( Hue / Saturation / Lightness ) هو مجرد تمثيل لوني مختلف.

باستخدام هذا التمثيل يكون من الأسهل ضبط السطوع.لذا، قم بالتحويل من RGB إلى HSV، وقم بزيادة سطوع "V"، ثم قم بالتحويل مرة أخرى إلى RGB.

يوجد أدناه بعض رموز C للتحويل

void RGBToHSV(unsigned char cr, unsigned char cg, unsigned char cb,double *ph,double *ps,double *pv)
{
double r,g,b;
double max, min, delta;

/* convert RGB to [0,1] */

r = (double)cr/255.0f;
g = (double)cg/255.0f;
b = (double)cb/255.0f;

max = MAXx(r,(MAXx(g,b)));
min = MINx(r,(MINx(g,b)));

pv[0] = max;

/* Calculate saturation */

if (max != 0.0)
    ps[0] = (max-min)/max;
else
    ps[0] = 0.0; 

if (ps[0] == 0.0)
{
    ph[0] = 0.0f;   //UNDEFINED;
    return;
}
/* chromatic case: Saturation is not 0, so determine hue */
delta = max-min;

if (r==max)
{
    ph[0] = (g-b)/delta;
}
else if (g==max)
{
    ph[0] = 2.0 + (b-r)/delta;
}
else if (b==max)
{
    ph[0] = 4.0 + (r-g)/delta;
}
ph[0] = ph[0] * 60.0;
if (ph[0] < 0.0)
    ph[0] += 360.0;
}

void HSVToRGB(double h,double s,double v,unsigned char *pr,unsigned char *pg,unsigned char *pb)
{
int i;
double f, p, q, t;
double r,g,b;

if( s == 0 )
{
    // achromatic (grey)
    r = g = b = v;
}
else
{
    h /= 60;            // sector 0 to 5
    i = (int)floor( h );
    f = h - i;          // factorial part of h
    p = v * ( 1 - s );
    q = v * ( 1 - s * f );
    t = v * ( 1 - s * ( 1 - f ) );
    switch( i )
    {
    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;
    default:        // case 5:
        r = v;
        g = p;
        b = q;
    break;
    }
}
r*=255;
g*=255;
b*=255;

pr[0]=(unsigned char)r;
pg[0]=(unsigned char)g;
pb[0]=(unsigned char)b;
}

ريتش نيومان يناقش لون HSL فيما يتعلق بـ .NET System.Drawing.Color على مدونته وحتى يوفر فئة HSLColor هذا يفعل كل العمل بالنسبة لك.قم بتحويل System.Drawing.Color إلى HSLColor، وأضف/اطرح القيم مقابل Luminosity، وقم بالتحويل مرة أخرى إلى System.Drawing.Color لاستخدامه في تطبيقك.

يمكنك تحويل اللون الخاص بك إلى مساحة ألوان HSL، ومعالجته هناك وتحويله مرة أخرى إلى مساحة الألوان التي تختارها (على الأرجح أنها RGB)

الألوان الفاتحة لها قيمة L أعلى، والأغمق لها قيمة أقل.

إليك الأشياء ذات الصلة وجميع المعادلات:

http://en.wikipedia.org/wiki/HSL_color_space

هناك طريقة أخرى تتمثل في دمج لونك باللون الأبيض أو الأسود.سيؤدي هذا أيضًا إلى عدم تشبع اللون قليلاً ولكن حسابه أرخص.

لقد استخدمت ControlPaint.Dark() و .Light() في System.Windows.Forms.

أعتقد أنك تستخدم RGB مع قيم البايت (0 إلى 255) لأن هذا شائع جدًا في كل مكان.

للحصول على سطوع أكثر، قم بمتوسط ​​قيم RGB مع RGB باللون الأبيض.أو، للتحكم في مقدار السطوع، يمكنك مزجها بنسب معينة.يترك f تختلف من 0.0 إلى 1.0، ثم:

Rnew = (1-f)*R + f*255
Gnew = (1-f)*G + f*255
Bnew = (1-f)*B + f*255

للحصول على لون أغمق، استخدم RGB للون الأسود - والذي يجعل العمليات الحسابية أسهل، نظرًا لأن جميعها أصفار.

أترك التفاصيل مثل تحويل النتيجة مرة أخرى إلى بايت، وهو ما قد ترغب في القيام به على الأرجح.

إذا كنت تستخدم ألوان RGB فسأقوم بتحويل معلمات اللون هذه إلى HSL (درجة اللون، والتشبع، والخفة)، وقم بتعديل معلمة الخفة ثم قم بالتحويل مرة أخرى إلى RGB.ابحث في Google وستجد الكثير من نماذج التعليمات البرمجية حول كيفية إجراء تحويلات تمثيل الألوان هذه (RGB إلى HSL والعكس).

وهذا ما وجدته بسرعة:http://bytes.com/forum/thread250450.html

بافتراض أنك حصلت على اللون كـ RGB، قم أولاً بتحويله إلى مساحة ألوان HSV (تدرج اللون والتشبع والقيمة).ثم قم بزيادة/تقليل القيمة لإنتاج ظل أفتح/أغمق من اللون.ثم قم بالتحويل مرة أخرى إلى RGB.

إذا كانت ألوانك بتنسيق RGB (أو CMYK على الأرجح)، فيمكنك استخدام الطريقة الأولية إلى حد ما لزيادة قيمة كل مكون من مكونات اللون.على سبيل المثال، يتم تمثيل الألوان في HTML بثلاثة أرقام سداسية مكونة من رقمين.سيعطيك #ff0000 لونًا أحمر ساطعًا، والذي يمكن بعد ذلك أن يبهت عن طريق زيادة قيم مكونات G وB بنفس المقدار، مثل #ff5555 (يعطي لونًا أحمر أفتح).من المفترض أنه بالنسبة لألوان Hue وSaturation وLightness (HSL)، يمكنك فقط رفع المكون L، لكن لا يمكنني الجزم بذلك؛أنا أقل دراية بمساحة الألوان هذه.

وكما قلت، فإن هذه الطريقة بدائية للغاية.من ذكرياتي عن Live Messenger، يبدو أنك تحاول إنشاء تدرجات، والتي يمكن تطبيقها بسهولة تامة في Windows Presentation Foundation (WPF، جزء من .NET 3.0).يدعم WPF العديد من أنواع فرشاة التدرج المختلفة، بما في ذلك التدرجات الخطية والقطرية.

يمكنني أن أوصي بشدة بكتاب آدم ناثان إطلاق العنان لمؤسسة العرض التقديمي لـ Windows كمقدمة جيدة وشاملة لـ WPF.

هث

من الأفضل القيام بأي اختلافات في اللون في HSL/HSV.

الاختبار الجيد هو الاستيفاء بين قيمتين متكافئتين في مساحة RGB ومساحة HSL.يبدو المنحدر في مساحة HSL وكأنه تقدم طبيعي.في مساحة RGB يبدو عادةً غير طبيعي تمامًا.يعين HSL تصورنا لمساحة الألوان المرئية بشكل أفضل بكثير من RGB.

تبدو فكرة التحويل إلى HSV أو بعض مساحات الألوان الأخرى جيدة، وقد تكون ضرورية لعمل ألوان دقيق، ولكن للأغراض العادية قد لا يكون خطأ العمل في RGB كافيًا.أيضًا، قد يكون من الصعب التعامل مع الحالات الحدودية:RGB هي مساحة على شكل مكعب، في حين أن HSV ليست كذلك.في حالة العمل باستخدام قيم البايت، يمكنك الحصول على تعيينات متعدد إلى واحد وواحد إلى متعدد بين المسافات.قد يكون هذا مشكلة أو لا يكون اعتمادًا على التطبيق.YMMV

هذا موقع إلكتروني يلاحظ أنه يمكنك استخدام فئة ControlPaint ضمن مساحة الاسم BCL C# System.Windows.Forms.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top