[WPF] LinearGradientBrush - mooiere gradient

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • NickThissen
  • Registratie: November 2007
  • Laatst online: 09-09 10:50
Hoi,

Ik wil in een WPF applicatie graag gebruik maken van een mooie gradient van donker grijs naar iets donkerder grijs. Daarvoor gebruik ik uiteraard een simpele LinearGradientBrush met twee GradientStops met offset 0 en 1:
code:
1
2
3
4
  <LinearGradientBrush x:Key="GrayGradient" StartPoint="0,0" EndPoint="0,1">
        <GradientStop Offset="0" Color="#312f2e" />
        <GradientStop Offset="1" Color="#171614" />
    </LinearGradientBrush>


Omdat de kleuren zo dicht bij elkaar liggen is er echter geen mooie gradient mogelijk (er zijn nou eenmaal niet genoeg kleuren die er tussen liggen), dus zijn er heel duidelijk 'banden' te zien in de gradient.

Ik lees overal dat je hier niets tegen kunt doen, maar daar ben ik het toch niet mee eens. Ten eerste bevatten deze banden om een of andere reden ook af en toe kleur en is de gradient niet geheel grijs. Als ik met Photoshop de gradient 'desaturate' (de kleur eruit halen), dan ziet het al een stukje beter uit.

De tweede stap die een enorme verbetering met zich meebrengt (vind ik dan) is om de gradient te 'ditheren'. Ik weet niet hoe ik dat vertaal, maar Photoshop heeft daar een optie voor bij het tekenen van gradients. Als ik die optie gebruik en in Photoshop een gradient teken van dezelfde kleuren, dan mengt hij de banden een beetje samen door een soort van ruis toe te voegen. Het effect is niet te zien tenzij je in gaat zoomen, en het resultaat is dus een veel meer vloeiend ogende gradient.

Zie hier een screenshot. Links is een screenshot van de gradient zoals WPF hem tekent. In het midden is dezelfde screenshot maar dan zonder kleuren (desaturated door Photoshop). Rechts ten slotte is een gradient in Photoshop getekend met dithering.
Afbeeldingslocatie: http://www.nickthissen.nl/Images/Temp/tmpFC6A.png

Hier is nog een ingezoomde versie waar het verschil in detail te zien is:
http://www.nickthissen.nl/Images/Temp/tmp5342.png


Mijn vraag is dan ook simpel... Is er enige manier waarop ik de gradient kan tekenen zoals Photoshop dat doet, dus met dithering? Ik zie hier geen optie voor in de LinearGradientBrush, maar het zou anders kunnen heten, ik heb geen idee...

Bedankt!

Mijn iRacing profiel


Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Eerste wat me te binnen schiet: je zou eens kunnen proberen de gradient wat "groter" te maken en dan te resizen; maar hoe haalbaar dat is weet ik zo niet. Met wat geluk past .Net automatisch dithering toe.
Edit: een snel testje leert ons dat dat iig niet het geval is :P (Hoewel ik misschien iets over het hoofd zie).

Het Floyd-steinberg dithering algoritme is echter ook niet bepaald rocket science en moet je desnoods zelf ook kunnen implementeren; als 't niet al ergens kant-en-klaar vindbaar is. En er zijn nog zat alternatieve algoritmes.

[ Voor 33% gewijzigd door RobIII op 25-01-2012 01:47 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • NickThissen
  • Registratie: November 2007
  • Laatst online: 09-09 10:50
Hm, de algoritmes zelf lijken inderdaad niet heel moeilijk. Ik vraag me echter wel af hoe ik ze moet implementeren. Moet ik dan een nieuwe brush gaan maken ofzo? Ik kan wel overerven van GradientBrush, maar als ik kijk hoe LinearGradientBrush (bijvoorbeeld) geimplementeerd is dan gaat dat nooit goed komen ben ik bang, veel internal methods die ik allemaal niet kan gebruiken.

Enige andere optie die ik kan bedenken is om het element dat ik de gradient wil geven een ImageBrush als achtergrond te geven (dat bestaat toch?), dan zou ik dus een Image moeten maken, daar een gradient op tekenen (met een normale LinearGradientBrush) en daarna dithering toepassen... Maar dat lijkt me vrij traag, er moet toch wel een betere manier zijn?

Mijn iRacing profiel


Acties:
  • 0 Henk 'm!

  • Phyxion
  • Registratie: April 2004
  • Niet online

Phyxion

_/-\o_

Probeer eens een gradient aan de hand van de kleuren van het rechter plaatje, die zijn heel anders :)

'You like a gay cowboy and you look like a gay terrorist.' - James May


Acties:
  • 0 Henk 'm!

  • NickThissen
  • Registratie: November 2007
  • Laatst online: 09-09 10:50
Ja, die zijn anders omdat Photoshop dithering toepast, en dan krijg je dus iets van ruis en die is voor zover ik op het oog kan zien niet monochromatisch (dus zit iets van kleur in). Als je echter met WPF (zonder dithering) een gradient gaat tekenen van kleuren zo dicht bij elkaar krijg je altijd van die banden... Zelfs al doe je helemaal van wit naar zwart is het nog te zien (hoewel ze dan kleiner zijn dus minder duidelijk).

Mijn iRacing profiel


Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
Ik denk dat WPF dit gewoon aan de videokaart/-drivers overlaat en dat die niet aan dithering doen. WPF onderstuend geen dithering (bron). Dus of een effect eroverheen plaatsen (glass), of zelf wat programmeren/iets vinden om een dithered bitmap te genereren. :p

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

  • Phyxion
  • Registratie: April 2004
  • Niet online

Phyxion

_/-\o_

NickThissen schreef op woensdag 25 januari 2012 @ 11:29:
Hm, de algoritmes zelf lijken inderdaad niet heel moeilijk. Ik vraag me echter wel af hoe ik ze moet implementeren. Moet ik dan een nieuwe brush gaan maken ofzo? Ik kan wel overerven van GradientBrush, maar als ik kijk hoe LinearGradientBrush (bijvoorbeeld) geimplementeerd is dan gaat dat nooit goed komen ben ik bang, veel internal methods die ik allemaal niet kan gebruiken.

Enige andere optie die ik kan bedenken is om het element dat ik de gradient wil geven een ImageBrush als achtergrond te geven (dat bestaat toch?), dan zou ik dus een Image moeten maken, daar een gradient op tekenen (met een normale LinearGradientBrush) en daarna dithering toepassen... Maar dat lijkt me vrij traag, er moet toch wel een betere manier zijn?
Ik denk dat je toch zoiets moet gaan doen, tenzij je zelf ook meteen een gradient wilt maken (wanneer je maar twee kleuren nodig hebt is dit nog aardig te implementeren). Echter, is het zo'n groot probleem om het gewoon op default te laten? Ik kan mij niet voorstellen dat het zo ontzettend belangrijk is om dithering toe te passen :)

'You like a gay cowboy and you look like a gay terrorist.' - James May


Acties:
  • 0 Henk 'm!

  • NickThissen
  • Registratie: November 2007
  • Laatst online: 09-09 10:50
Het is niet ontzettend belangrijk nee, ik stoor me er gewoon aan ;) Ik vroeg me af of het gemakkelijk te implementeren valt, en ik denk dat er wel een nette manier is die ik nog niet heb gevonden. Ik ga er in ieder geval geen uren tijd in stoppen maar het zou wel leuk zijn als ik wat mooiere gradients kon maken :)

Wellicht dat ik deze week nog eens probeer wat op te zetten, m'n grootste probleem is dat ik in WPF eigenlijk nog nooit echt aan image manipulation heb gedaan (dus bijv pixel voor pixel een afbeelding veranderen). Ik heb wel eens gelezen dat dat makkelijk en snel kan (met WriteableBitmap ofzoiets?) maar nog nooit in detail naar gekeken. Dat ga ik maar eens doen dan :)

Mijn iRacing profiel


Acties:
  • 0 Henk 'm!

  • SaphuA
  • Registratie: September 2005
  • Laatst online: 10-09 22:00
.

[ Voor 99% gewijzigd door SaphuA op 31-01-2022 15:40 ]

Pagina: 1