-
Re: [RESOLVED] My Potions are too strong for you Traveller. Cairo Hue Shift?
Quote:
Originally Posted by
dilettante
Those ShLwAPI calls only use 0-240 for the 3 elements even though 16-bit WORD arguments are used. Weird, hmm?
That isn't the only weird thing. The fact that they are using 16-bit WORDs at all is weird. Saturation, luminance and brightness in the HSB and HSL colour spaces are usually represented with floats between 0.0 and 1. Just about any code you find online treat these components as percentages.
Quote:
Originally Posted by
dilettante
I used a hack for those oddball colors. If the "adjusted" color is black but the original color was not black... I restored the original color of that pixel and moved on to premultiply.
It seems that the ShLwAPI calls "blackhole" any colors not within their colorspace, i.e. return 0 without any other error indication.
I find this interesting. My own HSL code has no problem handling any colour in the RGB space yet ShwAPI rejects some of them. I would really love to know why it rejects them. Whatever it's doing was very beneficial in this specific case.
However, when I compare what I did in PixelPainter to what you did in this sample, there are some differences. For example, you add the hue angle from the sliders to the hue angle of the pixels whereas I just give all the pixels the slider's hue angle. You did the same for saturation. Perhaps there is something in these differences.
-
Re: [RESOLVED] My Potions are too strong for you Traveller. Cairo Hue Shift?
In my code the values passed in are +/- delta (change) values.
I cycle the modified Hue to within the 0-240 range but I clamp modified Luminance and Saturation to the range because that seems to make more sense.
I also think I should change my CopyAdjustedPremultipled() to CopyAdjusted() with a Boolean argument Premultiply similar to my Load() method. I don't think saving premultiplied alpha into PNG format is valid. But I'm no expert, perhaps PNG format contains a flag for straight vs. premultiplied?
-
Re: [RESOLVED] My Potions are too strong for you Traveller. Cairo Hue Shift?
It's been years since I played around with inner workings of the PNG format but I seem to recall pre-multiplied alphas being valid in them. I can't remember the circumstances though. PNG is an extremely flexible format. It's made up of headered chucks. People can put all kinds of data into different kinds of chunks without breaking the format.
-
Re: [RESOLVED] My Potions are too strong for you Traveller. Cairo Hue Shift?
Quote:
Originally Posted by
dilettante
but I clamp modified Luminance and Saturation to the range because that seems to make more sense.
This is what confuses me. Anything that is not the hue is usually represented by percentages between 0% and 100%. I'm not sure why that API is structured the way it is.
-
Re: [RESOLVED] My Potions are too strong for you Traveller. Cairo Hue Shift?
Ah ok. I was able to successfully re-create the behavior of your application in PixelPainter by simply adding this line to my application:-
Code:
If hsl.Saturation < 0.3 Then Continue For
This ignores all pixels with a saturation of less than 30%:-
https://www.youtube.com/watch?v=ZUJAiqZ5EIg
So the the final solution to OP's question is to hue rotate in the HSL colour space while ignoring all pixels with a low saturation for example less than 30%. Though I can't say this will work ideally for all his bottle sprites. I only tested it on the two he provided. But I'm fairly satisfied that we have a workable solution.
-
Re: [RESOLVED] My Potions are too strong for you Traveller. Cairo Hue Shift?
Quote:
Originally Posted by
-Corso->
Olaf, did something go a bit funny? The little leather bits didn't alter and there was a brown spot on the glass.
Attachment 185027
That's because you probably did not adapt the Saturation-Interval Filter-Settings
(which I've set to [0.75 ... 1.0] in my Demo-Code)...
Here is the Mouse_Move Event again, which shows these Filter-Settings in red:
Code:
Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
If Button = 0 Then Exit Sub 'do nothing, until the User presses a MouseKey whilst moving
Dim HueAngle As Long, Result As cCairoSurface
HueAngle = (X + Y) / (ScaleWidth + ScaleHeight) * 360
Caption = "Current HueAngle: " & HueAngle & "°"
New_c.Timing True
Set Result = HueRotate(Src, HueAngle, 0.75, 1) '<- the Saturation-FilterInterval is optional
Caption = Caption & New_c.Timing
Result.DrawToDC hDC
End Sub
To produce "results like everybody else", you can just leave out these last optional Interval-Params
(which then would default to the all-pixels range-condition of [0 ... 1]).
I still think that theses Optional Filters in the HueRotate-function are "nice to have"
especially since I've now incorporated this into cCairoSurface as a Method, callable like this:
Set ResultSrf = Src.HueRotate(HueAngle, 0, 1)
or - as said - leaving the Filters out completely, will behave the same (still using the [0, 1] interval):
Set ResultSrf = Src.HueRotate(HueAngle)
HTH
Olaf
-
Re: [RESOLVED] My Potions are too strong for you Traveller. Cairo Hue Shift?
Quote:
Originally Posted by
Schmidt
That's because you probably did not adapt the Saturation-Interval Filter-Settings
(which I've set to [0.75 ... 1.0] in my Demo-Code)...
Here is the Mouse_Move Event again, which shows these Filter-Settings in
red:
Code:
Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
If Button = 0 Then Exit Sub 'do nothing, until the User presses a MouseKey whilst moving
Dim HueAngle As Long, Result As cCairoSurface
HueAngle = (X + Y) / (ScaleWidth + ScaleHeight) * 360
Caption = "Current HueAngle: " & HueAngle & "°"
New_c.Timing True
Set Result = HueRotate(Src, HueAngle, 0.75, 1) '<- the Saturation-FilterInterval is optional
Caption = Caption & New_c.Timing
Result.DrawToDC hDC
End Sub
To produce "results like everybody else", you can just leave out these last optional Interval-Params
(which then would default to the all-pixels range-condition of [0 ... 1]).
I still think that theses Optional Filters in the HueRotate-function are "nice to have"
especially since I've now incorporated this into cCairoSurface as a Method, callable like this:
Set ResultSrf = Src.
HueRotate(HueAngle,
0, 1)
or - as said - leaving the Filters out completely, will behave the same (still using the [0, 1] interval):
Set ResultSrf = Src.
HueRotate(HueAngle)
HTH
Olaf
Set it to rotate only pixels with saturation values above 30%. That seems to work well, at least with the two sprites he provided. For untested sprites, he could play around with different filter settings like you mentioned. Most often though, I'd expect some variation of filtering based on saturation.
-
Re: [RESOLVED] My Potions are too strong for you Traveller. Cairo Hue Shift?
Also, and I can't say with 100% certainty, but I get the feeling that HSL is a better colour space than HSB for this.
-
1 Attachment(s)
Re: [RESOLVED] My Potions are too strong for you Traveller. Cairo Hue Shift?
Attachment 185029
Pure fantasy madness...
I loves it.
Ah, thanks for the explanation Olaf.
-
2 Attachment(s)
Re: [RESOLVED] My Potions are too strong for you Traveller. Cairo Hue Shift?
My final version now supports a third Filter-pair for existing Hue-intervals.
(and will be present as a Method, directly on cCairoSurface in the next release).
Mission: "Save the corc!" (the new Angle-filter-pair makes this possible)
Here's the result of a 300° rotated image ...
(from the original, which had the fluid in a "red-tint" within Hue-Range 0-12):
Attachment 185030
So, the Method-Call for this filter-setting is obviously:
Set Result = HueRotate(Src, HueAngle, , , , , 0, 12) '<- perform stuff only on "the fluid" and not "the corc"
Here's the Project-Zip for those interested.
Attachment 185031
Olaf
-
Re: [RESOLVED] My Potions are too strong for you Traveller. Cairo Hue Shift?
Quote:
Originally Posted by
dilettante
I cycle the modified Hue to within the 0-240 range but I clamp modified Luminance and Saturation to the range because that seems to make more sense.
I'm sure there are published specifications for this in the HSL color-space (for which I have not looked). But, to my way of thinking, if we always return to three values, for RGB, luminance and saturation are represented by two different measures from these RGB values: 1) Luminance represented by the value of all three values summed, and 2) Saturation is represented by the deltas in the three values. If you like, just calculate the absolute value of all six deltas and sum them, and that'll be a representation of Saturation.
Therefore, when we "rotate" these values in a way that maintains the sum and the sum of the deltas, we're changing Hue.
I also agree that the HSL color-space is much better than the HSV color-space. HSL is just much better at "adjusting" colors. However, for my core thinking, I always tend to go back to RGB because that's what our monitor's pixels emit, and it's also representative of the three "true" colors that our photo-receptors (in our eyes) can see. There are truly only three "color" receptors in our eyes: red, green, & blue. The rest is additive light mixing.
-
Re: [RESOLVED] My Potions are too strong for you Traveller. Cairo Hue Shift?
If a pixel has luminance of 240 then adding more luminance is meaningless, so after adding the positive delta (even just 1) you have to clamp the value to 240. Opposite for negative deltas that would take luminance below 0.
That's what "clamping" means.
Maybe I misunderstood your point?
Also, we don't simply "see RGB" that's a gross oversimplification. Only one among many issues is the different spectral widths and positions each type of cone responds to, not to mention color sensitivity of each type. There is also the contribution of rod input, as well as person to person differences including a 4th type of cone in some people.
But the various colorspaces are just simplified abstractions facilitating different technologies. CYMK anyone?
-
Re: [RESOLVED] My Potions are too strong for you Traveller. Cairo Hue Shift?
I found this:
PNG (Portable Network Graphics) Specification
Version 1.0
Quote:
12.8. Non-premultiplied alpha
PNG uses "unassociated" or "non-premultiplied" alpha so that images with separate transparency masks can be stored losslessly. Another common technique, "premultiplied alpha", stores pixel values premultiplied by the alpha fraction; in effect, the image is already composited against a black background. Any image data hidden by the transparency mask is irretrievably lost by that method, since multiplying by a zero alpha value always produces zero.
Some image rendering techniques generate images with premultiplied alpha (the alpha value actually represents how much of the pixel is covered by the image). This representation can be converted to PNG by dividing the sample values by alpha, except where alpha is zero. The result will look good if displayed by a viewer that handles alpha properly, but will not look very good if the viewer ignores the alpha channel.
Although each form of alpha storage has its advantages, we did not want to require all PNG viewers to handle both forms. We standardized on non-premultiplied alpha as being the lossless and more general case.
No idea whether this was ever changed to add exceptions. Of course not all software is always fully spec-compliant either.
-
Re: [RESOLVED] My Potions are too strong for you Traveller. Cairo Hue Shift?
-
Re: [RESOLVED] My Potions are too strong for you Traveller. Cairo Hue Shift?
Quote:
Originally Posted by
dilettante
Also, we don't simply "see RGB" that's a gross oversimplification.
Hi Dil. :) Yeah, I think we're in agreement on what Saturation and Luminance are.
But, unless they've learned more about our cone photoreceptors since I took those neuroanatomy classes, we really do only see Red, Green, & Blue. Now sure, we have "night-time" rods, and they've also discovered some peripheral retinal receptors that sense motion, but those are really separate issues. For "day" vision, it's all Red, Green, & Blue.
Now, each of those RGB photoreceptors do fire with varying intensities, and that can happen for two reasons: 1) the light is dim, or 2) the light frequency isn't "tuned" to the perfect color "red" (or "green" or "blue"). In fact, they've worked out complete bell curves for how off-perfect hues make those receptors fire.
But, the neural impulse coming out of the back, and going to the brain, is still just a certain intensity of red (or green or blue). And then, our brain sees (maybe) both red and green firing in a particular spot and then tells us to "see" yellow (etc). In other words, it's our brain that does the mixing, not our photoreceptors.
All of that is precisely why our monitors only have to emit red and green and blue (absolutely no other colors), and are able to give the appearance that they can display any visible color. It's fun to get a hand-held microscope and put it up to a monitor and actually see this. Each pixel is literally a triad of RGB sub-pixels, that are frequency tuned to our retinal cone photoreceptors.
-
Re: [RESOLVED] My Potions are too strong for you Traveller. Cairo Hue Shift?
Tetrachromacy: Do you have superhuman vision?
Quote:
What is tetrachromacy?
Tetrachromacy is a condition where a person has four cone types in their retina, rather than the standard three that most people have. It occurs as a result of a genetic mutation and can only occur in women. This is because the gene for our red and green cone types is on the X chromosome (women have two X chromosomes, while men have one X chromosome and one Y chromosome). This means that, very occasionally, women can receive two different versions of the gene, “each encoding for a cone that is sensitive to slightly different parts of the spectrum”. If a man has a genetic mutation on the X chromosome (as he only has one X chromosome) it would result in him being colour blind, rather than tetrachromatic.
Ok, it is rare enough we can probably ignore it. ;)
-
Re: [RESOLVED] My Potions are too strong for you Traveller. Cairo Hue Shift?
hahahaha, well, I know the computer industry ignores it.
hahaha, also, on another point, you can take various substances (most specifically betacarotine) that will shift the frequencies (i.e., colors) that your cones see. I think it was WWII where the military was massively dosing volunteers with betacarotine to see if they could develop some degree of infra-red vision (but then they engineered the infra-red scopes).
Also, as far as we know, dogs only have two types (colors) of cones. I've often wondered what that looks like, but I suspect that we just need to ask a color-blind person, as the vast majority of those are just missing one of the color cones.
Added: Or, just take a color TV driven by a component signal, and unplug one of the colors.
-
Re: [RESOLVED] My Potions are too strong for you Traveller. Cairo Hue Shift?
Quote:
Originally Posted by
argen
Good find, thanks!
Quote:
The upper value of the range is not reached because Hue is cyclical, so a value of 360° is equivalent to 0°. On the other hand, Saturation and Luminance are floating point values between 0.0 and 1.0 (inclusive).
-
Re: [RESOLVED] My Potions are too strong for you Traveller. Cairo Hue Shift?
And just as a final comment, that's why I'll never get away from thinking of all of this in RGB terms, while admitting that the HSL approach is often superior for artistic and design purposes. :)
-
Re: [RESOLVED] My Potions are too strong for you Traveller. Cairo Hue Shift?
Quote:
Originally Posted by
Elroy
And just as a final comment, that's why I'll never get away from thinking of all of this in RGB terms, while admitting that the HSL approach is often superior for artistic and design purposes. :)
But with HSL you can do adjustments that with RGB you can't.
How would you add more saturation with RGB, or less luminosity?
-
Re: [RESOLVED] My Potions are too strong for you Traveller. Cairo Hue Shift?
Argen, you can do "anything" with RGB. It's just not necessarily as easy as it is with HSL. That was my point in saying "often superior for artistic and design purposes".
To increase luminosity with RGB, just proportionally raise each of your R, G, B values.
To add saturation, you'd spread the R, G, B values farther away from each other (taking the overall color further from gray).
-
Re: [RESOLVED] My Potions are too strong for you Traveller. Cairo Hue Shift?
One problem i have seen is choosing a text color to print onto a colored background. You usually need to choose a text color that contrasts with the back color as much as possible for best legibility.
It isn't as simple as that, but using a sort of "complement mod 241" of the HSV components gets you a close approximation pretty quickly.
Code:
Option Explicit
Private Const CC_ANYCOLOR = &H100
Private Const CC_RGBINIT = &H1
Private Const CC_FULLOPEN = &H2
Private Const CC_PREVENTFULLOPEN = &H4
Private Type CHOOSECOLOR
lStructSize As Long
hwndOwner As Long
hInstance As Long
rgbResult As Long
lpCustColors As Long
Flags As Long
lCustData As Long
lpfnHook As Long
lpTemplateName As Long
End Type
Private Declare Function ChooseColorW Lib "comdlg32" ( _
ByRef CHOOSECOLOR As CHOOSECOLOR) As Long
Private Declare Function ColorHLSToRGB Lib "shlwapi" ( _
ByVal wHue As Integer, _
ByVal wLuminance As Integer, _
ByVal wSaturation As Integer) As Long
Private Declare Sub ColorRGBToHLS Lib "shlwapi" ( _
ByVal clrRGBNew As Long, _
ByRef wHue As Integer, _
ByRef wLuminance As Integer, _
ByRef wSaturation As Integer)
Private Declare Function GetSysColor Lib "user32" (ByVal nIndex As Long) As Long
Private CHOOSECOLOR As CHOOSECOLOR
Private CustomColors(0 To 15) As Long 'Buffer to retain user's settings.
Private Sub Command1_Click()
Const MESSAGE As String = "Testing, testing... Hello World!"
Dim wHue As Integer
Dim wLuminance As Integer
Dim wSaturation As Integer
Dim Msg As String
With CHOOSECOLOR
.hwndOwner = hWnd
.lpCustColors = VarPtr(CustomColors(0))
If BackColor < 0 Then
.rgbResult = GetSysColor(BackColor And &HFFFF&)
Else
.rgbResult = BackColor
End If
If ChooseColorW(CHOOSECOLOR) <> 0 Then
BackColor = .rgbResult
ColorRGBToHLS BackColor, wHue, wLuminance, wSaturation
wHue = (wHue + 119) Mod 240
wLuminance = (wLuminance + 120) Mod 241
wSaturation = (wSaturation + 120) Mod 241
ForeColor = ColorHLSToRGB(wHue, wLuminance, wSaturation)
CurrentX = (ScaleWidth - TextWidth(MESSAGE)) / 2
CurrentY = 0
Print MESSAGE
Msg = "Back: &H" & Right$("0000000" & Hex$(BackColor), 8)
CurrentX = (ScaleWidth - TextWidth(Msg)) / 2
Print Msg
Msg = "Fore: &H" & Right$("0000000" & Hex$(ForeColor), 8)
CurrentX = (ScaleWidth - TextWidth(Msg)) / 2
Print Msg
End If
End With
End Sub
Private Sub Form_Load()
With CHOOSECOLOR
.lStructSize = LenB(CHOOSECOLOR)
.Flags = CC_ANYCOLOR Or CC_RGBINIT Or CC_FULLOPEN
End With
AutoRedraw = True
End Sub
-
Re: [RESOLVED] My Potions are too strong for you Traveller. Cairo Hue Shift?
Quote:
Originally Posted by
Elroy
Argen, you can do "anything" with RGB. It's just not necessarily as easy as it is with HSL. That was my point in saying "often superior for artistic and design purposes".
To increase luminosity with RGB, just proportionally raise each of your R, G, B values.
To add saturation, you'd spread the R, G, B values farther away from each other (taking the overall color further from gray).
I agree with Argen, or at least his underlying point. PixelPainter isn't the first sprite colouring tool I ever wrote, I actually wrote one more than a decade ago. Hell in the screenshot it's running on Windows XP. Anyways, in those days I was very ignorant to a lot of things which included a broader understanding of colour spaces. I naively wrote the damn thing to recolour sprites using the RGB colour space and let me tell you, I still remember how frustrating it was to get the exact colours you wanted because you be could be comfortably shifting throught a red hue and end up right into a purple all of a sudden.
RGB is really only good when you don't care what the colours look like. If you're just interested is raw number crunching for various filters like converting to grayscale, then RGB is perfectly fine. But when you start caring about how certain colours would look, you really don't want to use RGB. I learned this first hand. RGB is cubic and unintuitive for "guessing" colours. HSB and HSL have conic a geometry with hues distributed about the circumference which is highly intuitive when one needs to speculate.
-
Re: [RESOLVED] My Potions are too strong for you Traveller. Cairo Hue Shift?
Quote:
Originally Posted by
Elroy
Argen, you can do "anything" with RGB. It's just not necessarily as easy as it is with HSL.
I agree, you can do anything with RGB, but if you convert the bits to HSL.
With RGB you can do little.
Quote:
That was my point in saying "often superior for artistic and design purposes".
I can't agree. Artistic might be one route of applications only, there can be many non-artistic app that could need to change colors.
Quote:
Originally Posted by
Elroy
To increase luminosity with RGB, just proportionally raise each of your R, G, B values.
Probably not that easy. How much (percent, 1 or 256 based) is the luminosity from which you start?
Then you want to increase the luminosity to 99%,
and after that decrease it to 50%
How would you do that with RGB?
Quote:
To add saturation, you'd spread the R, G, B values farther away from each other (taking the overall color further from gray).
If you do a lot of match you could do anything. The problem is that you basically will be converting to HSL or something similar every time.