الصلب نحو أو بعيدًا عن اللون بنسبة مئوية معينة
سؤال
أحاول محاكاة تأثير الصبغة من Open XML. ما تفعله هو تغيير لون البكسل في صورة عن طريق تحويل اللون. يستغرق 2 معلمات: 1) hue
(بالدرجات) و 2) amt
(المبلغ ، نسبة مئوية). إنه رقم 2 أواجه مشكلات معها. تنص المواصفات:
لون: تحول تأثير قيم الألوان إما نحو أو بعيدًا عن اللون من خلال المبلغ المحدد.
- AMT (المبلغ) - يحدد بمقدار قيمة اللون.
- مسحة (Hue) - يحدد الصبغ الذي يجب أن تلميح.
لا تمانع في بناء XML ، يمكنني محاكاة القيم التي تحتوي على amt
من 100 ٪. على سبيل المثال ، إذا أردت اللون الأزرق (Hue: 240 °) ، يمكنني إنشاء هذا ( ملون واحد). هذا مثال:
إبداعي و ملون (Hue = 240 ، المبلغ = 100 ٪).
يتم تحقيق ذلك ببساطة عن طريق ضبط Hue إلى 240 ، مع الحفاظ على التشبع والخمياء كما هو والتحويل إلى RGB وكتابة كل بكسل.
هذا ما لا يمكنني تحقيقه على الرغم من:
Hue =240 (أزرق) ، كمية = 30%, 50% و 80%, ، على التوالى
مرة أخرى ، المواصفات ل Amount
يقول يحدد بمقدار قيمة اللون. لقد جربت كل أنواع الطرق هنا للحصول على هذا العمل ، لكن لا يمكن أن يبدو (hue=hue*amount
, originalhue * amount + hue
, ، إلخ.)
المزيد من الأمثلة: Hue =120 (لون أخضر) ، كمية = 30%, 50%, 80% و 100%, ، على التوالى. ال 100% واحد يمكنني الحصول عليه.
فيما يلي بعض قوائم القيمة لبكسل واحد في الصور أعلاه:
بكسل 159 ، 116 - صور زرقاء
Hue المبلغ RGB | HSL الأصلي 244 196 10 | 48 0.92 0.5 Blue 240 30% 237 30 45 | 356 0.85 0.52 Blue 240 50% 245 9 156 | 323 0.93 0.5 Blue 240 80% 140 12 244 | 273 0.91 0.5 Blue 240 100% 12 12 244 | 240 0.91 0.5
بكسل 159 ، 116 - صور خضراء
Hue المبلغ RGB | HSL الأصلي 244 196 10 | 48 0.92 0.5 Green 120 30% 211 237 30 | 68 0.85 0.52 Green 120 50% 159 237 30 | 83 0.85 0.52 Green 120 80% 81 237 29 | 105 0.85 0.52 Green 120 100% 29 237 29 | 120 0.85 0.52
لذا ، فإن السؤال هو: هل يعرف أي شخص كيف يجب أن يعمل هذا؟
ملاحظة: هذا هو ليس مكررة من:
- تغيير صبغة صورة نقطية مع الحفاظ على السطوع العام
- تدوير اللون باستخدام ImageAttributes في C#
- ... أو أي شيء آخر يمكن أن أجده على ذلك
المحلول
أنا متأكد تمامًا من أن مشكلتك تنتج عن الطريقة التي تتداخل بها الزوايا. إليك وظيفة الاستيفاء (مكتوبة في بيثون) يجب أن تفعل الخدعة. يعتمد على اقتراح من موضوع منتديات XNA أقصر استيفاء زاوية ثنائية الأبعاد.
def wrap(value, lower, upper):
distance = upper - lower
return value - ((value-lower)//distance)*distance
def shortestangle(a,b):
angle = wrap(b-a, 0, 360)
if angle>=180: angle -= 360
return angle
def interpolate(a,b,amount):
return (a+shortestangle(a,b)*amount)%360
حاليا، interpolate(originalHue,hue,amount)
يجب أن تنتج النتيجة المرجوة.
يحرر: أفهم أن هدفك هو تدوير اللون الأصلي نحو صبغة مستهدفة معينة بمبلغ معين. أنا متأكد من أنك على دراية بهذا بالفعل ، ولكن من أجل التوضيح ، إليك عجلة ملونة.
(مصدر: sapdesignguild.org)
المشكلة هي أن الخلط (أو التداخل) زاويتان ليسوا تافهة ، لذلك مثل الكود hue = ((hue - originalHue) * amount) + originalHue
لن يعمل. هناك عدد لا حصر له من الطرق التي يمكنك من خلالها الانتقال من زاوية إلى أخرى بسبب التفاف عند 360 درجة. للوصول من 0 درجة إلى 60 درجة ، يمكنك تدوير 60 درجة في اتجاه عقارب الساعة ، و 420 درجة في اتجاه عقارب الساعة ، و 300 درجة في اتجاه عقارب الساعة ، إلخ. عادة ما تكون الزاوية الأقصر هي الزاوية المطلوبة.
على سبيل المثال ، دعنا ننظر في رقاب البطريق: إذا كان اللون الأصلي الخاص بك هو 30 درجة (برتقالي) ، فإن هدفك هو 240 درجة (أزرق) والمبلغ 50 ٪ ، فستحصل على النتائج التالية:
//Linear Interpolation
(30° + (240° - 30°)*0.5) = 135° (green)
//"Shortest 2D Angle Interpolation"
(30° + shortestangle(30°,240°)*0.5) % 360 = (30° + (-150°)*0.5) % 360 = 315° (magenta)
أظن أن النتيجة الثانية هي النتيجة التي تبحث عنها ، لكنني قد أكون مخطئًا وقد يكون الخطأ في مكان آخر تمامًا ...
نصائح أخرى
يجب عليك إلقاء نظرة على tintparams في GDI+ (ليس جزءًا من .NET) - قد يكون هذا مجرد ما تبحث عنه.