-
2 Attachment(s)
[RESOLVED] My Potions are too strong for you Traveller. Cairo Hue Shift?
Hi Cairo Squad,
I've been testing another autobuilder, but came to an abrupt halt.
Short version, handmade Photoshop sketch tests, thought they looked particularly cool, made a Cairo re-assembler to make many, however, colours were horribly skewed from the Photoshop ideals (bright areas dropped, colourization too hot etc). I've had to reassess the builder and am now starting from scratch.
I just noticed one thing, that would make everything easy peasy. Hue Shifting.
I was wondering if people know how to do this in Cairo?
This is what you do in Photoshop.
Attachment 184978
Saturation is easy as you only need to place a grey surface over the original image. But actual hue shifting? I tried various Photoshoppy addition layers, like adding a hue layer in a different colour, but it's all wrong. So I'm wondering if Cairo has a way of hue shifting? The reason I ask, is because if I add a hue layer to the original image it overwrites ALL hues, meaning a red potion with orange glow becomes soley green for example. It looks pretty foul to be honest. Basically the underlayer with multiple colours becomes a bland single colour.
These are my handmade Premade-Proper-Photoshop-Pixel-Potions-Picked-A-Pepper-Or-Two I'm trying to replicate. Thanks for help!
Attachment 184979
-
Re: My Potions are too strong for you Traveller. Cairo Hue Shift?
If I understand correctly you want to be able to change the hue of an image without needing Photoshop. Perhaps you want your own code to do it through Cairo. Now I can't say whether Cairo can do it, I'll leave that to Olaf since he is the resident Cairo expert.
However, in the event that Cairo can't do what you want, I offer this: Changing the hue of an image, while I won't say it's easy, it's not exactly difficult either. We're all used to dealing with colours using the RGB colour space however, it is not the only colour space. There are many colour spaces and the ones you need to be dealing with are the HSL or HSB colour spaces. So what you do is you get all the pixel values of the image which will be in RGB format and from there you have to convert all of them to HSL or HSB from there you can change the hue values of each pixel by adding or subtracting to and from the hue value of each pixel.
It should be quite easy to find an algorithm to convert from RGB to HSL/HSB online if this Cairo thing doesn't work out and you have to do it yourself. Also, I wrote a small application for recolouring sprites which does this through the HSL colour space. You can check it out here if you want. It's written in VB.Net but perhaps you can look at it for ideas. It uses no 3rd party image libraries or anything like that for recolouring sprites so the code is all there showing how to do it.
-
Re: My Potions are too strong for you Traveller. Cairo Hue Shift?
Maybe you can get some ideas from Tanner Helland's Photodemon
It's all written in VB6, and open-source
-
2 Attachment(s)
Re: My Potions are too strong for you Traveller. Cairo Hue Shift?
Thanks Niya, though I can't read your files... :) I don't have .Net installed anymore. Can I open one in word pad perhaps, which file?
Attachment 184983
Thanks Arnoutdv I'll take a looksee.
Though I was looking at other code chunks to slide HSB around, but it was all Python, C, Sea-flea and god knows what else. I'm not proficient to understand the complexities of what they were doing this time. Normally one can guess the similar components but nothing was apparent. I'll keep looking until I submit to my,,,, *drum roll*
A Last Minute Trashy Workaround! Tadah!
Attachment 184982
Behold in all it's god awful glory. Ligthen layers of R(Normal), G and Beeeee. I think I can randomize all these to make various shifts, sort of. It kind of actually works much to my surprise. If nothing is apparent I'll just use this dodgy method.
-
Re: My Potions are too strong for you Traveller. Cairo Hue Shift?
Well just to be clear, you want the ability to recolour sprites by changing the hue, right? So you can create different colour bottles from a single base, is this right? I was guessing that is what you were looking for based on your OP but I wasn't 100% sure.
-
Re: My Potions are too strong for you Traveller. Cairo Hue Shift?
Quote:
Originally Posted by
Niya
Well just to be clear, you want the ability to recolour sprites by changing the hue, right? So you can create different colour bottles from a single base, is this right? I was guessing that is what you were looking for based on your OP but I wasn't 100% sure.
Yes.
The trashy workaround I 'just' thought up a moment ago does this, sort of... It's not precisely predictable or code worthy, but the light levels stay perfect as do the hue shift. <- I have not been able to do this via Cairo or Photoshop 'Flat Layering' yet.
In the workaround, if I randomize alpha on the RGB layers in Cairo, that will be enough to alter the bottles appearance. I tried mucking around and all the vibrant colours stayed perfect, complete with tonal shifts. It's like fixing a car with a sledgehammer though...
-
Re: My Potions are too strong for you Traveller. Cairo Hue Shift?
Ok, so to be extra sure this is what you want to be able to do?
https://www.youtube.com/watch?v=G53Qn_cyPlQ
-
Re: My Potions are too strong for you Traveller. Cairo Hue Shift?
Yeah, just an entire 'image' or 'Cairo surface' hue shift. I don't need anything fancy.
Cairo is preferable, if it's available as a thing. Cairo seems to have a lot of built in art functions, but I haven't come across hue shift yet, only hue layer add. :o
-
Re: My Potions are too strong for you Traveller. Cairo Hue Shift?
Quote:
Originally Posted by
-Corso->
Yeah, just an entire 'image' or 'Cairo surface' hue shift. I don't need anything fancy.
Cairo is preferable, if it's available as a thing. Cairo seems to have a lot of built in art functions, but I haven't come across hue shift yet, only hue layer add. :o
Tell me, does Cairo allow you to access pixel data from it's surfaces? If that's the case, all you have to do is convert those pixel values from RGB to HSL or HSB. You can then set the hue of the pixels, convert them back to RGB and write them to the Cairo surface.
Also, how are you using Cairo? Are you using it through Olaf's RichClient library or are you using it through something else? The reason I ask is because if it's from RC5/6 then perhaps Olaf can help with this.
I could show you how to do it manually but it would take me forever write a working sample in VB6 since I'd have to rely on what I know which is GDI and that requires a lot of tedious boilerplate. I'm not looking forward to that at all :( Olaf could probably produce VB6 code for this far faster than I ever could.
-
Re: My Potions are too strong for you Traveller. Cairo Hue Shift?
Yes, RC6 does allow you to read and write pixel data. (BindToArray). I can do that to grab RGB and Alpha. Ah, so I just need to find the code to switch that to HSV. Nice!
-
Re: My Potions are too strong for you Traveller. Cairo Hue Shift?
https://www.geeksforgeeks.org/progra...v-color-model/
There's some c# ccode thtere that you might be able to adapt to your needs.
-tg
-
Re: My Potions are too strong for you Traveller. Cairo Hue Shift?
Ok I made an extremely barebones sample that demonstrates how to change an image's hue. Here's a 40 second video demonstrating it so you see what it looks like:-
https://www.youtube.com/watch?v=NDy9UBNk_vQ
I wanted to do the demo in VB6 but unfortunately I was unable to quickly find information on how to load an image from disk and access it's pixel data using RC6's Cairo. I didn't want to spend all day trawling these boards looking for that information. GDI was also out of the question since it would require a tonne of boilerplate I'd have to spend up to an hour writing and testing or ripping from old VB6 projects I haven't touched in like a decade plus. Instead I just banged it out in about 30 minutes in VB.Net.
Fortunately though, the important parts are extremely easy to understand and translate to VB6. I'll leave it to you to figure out all the Cairo stuff in VB6.
Now the core of all this as I've said is converting from RGB to HSB or HSL and back. I chose HSB since it's a tad bit simpler than HSL. Here is the code for converting RGB to HSB and back:-
Code:
Public Structure HSB
Public Sub New(hue As Integer, saturation As Double, brightness As Double)
Me.Hue = hue
Me.Saturation = saturation
Me.Brightness = brightness
End Sub
Public Property Hue As Integer
Public Property Saturation As Double
Public Property Brightness As Double
Public Overrides Function ToString() As String
Return $"Hue = {Me.Hue.ToString}, Saturation = {Me.Saturation.ToString}, Brightness = {Me.Brightness.ToString}"
End Function
End Structure
Public Class ColorConverter
Public Shared Function ColorToHSB(ByVal c As Color) As HSB
Return RGBToHSB(c.R, c.G, c.B)
End Function
Public Shared Function RGBToHSB(ByVal R As Byte, ByVal G As Byte, ByVal B As Byte) As HSB
Dim d_r As Double = R / 255
Dim d_g As Double = G / 255
Dim d_b As Double = B / 255
Dim max As Double = {d_r, d_g, d_b}.Max
Dim min As Double = {d_r, d_g, d_b}.Min
Dim diff As Double = max - min
Dim h As Integer
Dim s, v As Double
If max = min Then
h = 0
ElseIf max = d_r Then
h = (60 * ((d_g - d_b) / diff) + 360) Mod 360
ElseIf max = d_g Then
h = (60 * ((d_b - d_r) / diff) + 360) Mod 360
ElseIf max = d_b Then
h = (60 * ((d_r - d_g) / diff) + 360) Mod 360
End If
If max = 0 Then s = 0 Else s = diff / max
v = max
Return New HSB(h, s, v)
End Function
Public Shared Function HSBToRGB(ByVal hsb As HSB) As Color
Return HSBToRGB(hsb.Hue, hsb.Saturation, hsb.Brightness)
End Function
Public Shared Function HSBToRGB(ByVal hue As Integer, ByVal saturation As Double, ByVal value As Double) As Color
'JavaScript algorithm
'===============================================
' Const HSBToRGB = (h, s, b) >= {
' s /= 100;
' b /= 100;
' Const k = (n) >= (n + h / 60) % 6;
' Const f = (n) >= b * (1 - s * Math.Max(0, Math.Min(k(n), 4 - k(n), 1)));
' Return [255 * f(5), 255 * f(3), 255 * f(1)];
'};
'===============================================
Dim k = Function(n As Double) (n + hue / 60) Mod 6
Dim f = Function(n As Double) value * (1 - saturation * Math.Max(0, {k(n), 4 - k(n), 1}.Min))
Return Color.FromArgb(255, 255 * f(5), 255 * f(3), 255 * f(1))
End Function
End Class
The above is VB.Net code I know but it's really nothing more than mathematical formulas really. It should be very trivial to convert this to VB6.
Apply it to an image is also very trivial. Here is the VB.Net code I used:-
Code:
Public Sub SetImageHue(ByVal img As Bitmap, ByVal hue As Integer)
'Lock the Bitmap object to access it's bits
Dim bpData = img.LockBits(New Rectangle(0, 0, img.Width, img.Height), Imaging.ImageLockMode.ReadWrite, Imaging.PixelFormat.Format32bppArgb)
Dim A, R, G, B As Byte
For i As Integer = 0 To (bpData.Width * bpData.Height) - 1
'Read the colour components of each pixel
'from the Bitmap
B = Marshal.ReadByte(IntPtr.Add(bpData.Scan0, i * 4))
G = Marshal.ReadByte(IntPtr.Add(bpData.Scan0, i * 4), 1)
R = Marshal.ReadByte(IntPtr.Add(bpData.Scan0, i * 4), 2)
A = Marshal.ReadByte(IntPtr.Add(bpData.Scan0, i * 4), 3)
'Convert the pixel from the RGB colour space to
'the HSB colour space.
Dim hsb = ColorConverter.RGBToHSB(R, G, B)
'Set the hue of the pixel
hsb.Hue = hue
Dim c As Color = ColorConverter.HSBToRGB(hsb)
'Write the pixel back to the image
Marshal.WriteInt32(IntPtr.Add(bpData.Scan0, i * 4), c.ToArgb)
Next
'Unlock the bitmap
img.UnlockBits(bpData)
End Sub
The above is a function that sets the Hue of a Bitmap. It's very simple. You just enumerate all of the pixels in the image, convert the RGB components to HSB, set the hue you want, convert it back to RGB and write the new RGB values back to the image. Very easy stuff.
-
Re: My Potions are too strong for you Traveller. Cairo Hue Shift?
Thanks Niya. I'll examine this in detail. I'm actually dead tired and sore after a hospital visit, plus I have to go back in a few days. I'd like to write up the Cairo version using your formula as it's a good way for me to learn it for other colour adjustments in the future. Just going to rest for a few days before I post that though.
While there I coded up the lazybones version of mine too, for the, just in case scenario.
Thanks for posting. :)
-
2 Attachment(s)
Re: My Potions are too strong for you Traveller. Cairo Hue Shift?
Quote:
Originally Posted by
-Corso->
I'd like to write up the Cairo version using your formula...
Before you dive into your own Pixel-Loops, please check whether the function below -
(ApplyHueTo(...) is sufficient).
Code:
Option Explicit
Private CC As cCairoContext 'our global BackBuf-CC (derived from a Form-covering Surface)
Private Sub Form_Load()
Dim Src As cCairoSurface
Set Src = Cairo.ImageList.AddImage("Grey_Src", "c:\temp\potion_greyscale.png", 128, 128)
Cairo.ImageList.AddSurface "Hue_Green", ApplyHueTo(Src, vbGreen)
Cairo.ImageList.AddSurface "Hue_Yellow", ApplyHueTo(Src, vbYellow)
Cairo.ImageList.AddSurface "Hue_Magenta", ApplyHueTo(Src, vbMagenta)
Cairo.ImageList.AddSurface "Hue_Cyan", ApplyHueTo(Src, vbCyan)
Me.Move Left, 0, Width, Screen.Height
End Sub
Private Sub Form_Resize()
ScaleMode = vbPixels: AutoRedraw = True
Set CC = Cairo.CreateSurface(ScaleWidth, ScaleHeight).CreateContext
ReDraw
End Sub
Private Sub ReDraw()
CC.Paint 1, Cairo.CreateCheckerPattern(8, &H333333)
Dim i&
CC.RenderSurfaceContent "Grey_Src", 0, i * 128: i = i + 1
CC.RenderSurfaceContent "Hue_Green", 0, i * 128: i = i + 1
CC.RenderSurfaceContent "Hue_Yellow", 0, i * 128: i = i + 1
CC.RenderSurfaceContent "Hue_Magenta", 0, i * 128: i = i + 1
CC.RenderSurfaceContent "Hue_Cyan", 0, i * 128: i = i + 1
CC.Surface.DrawToDC hDC: Refresh
End Sub
Private Function ApplyHueTo(Src As cCairoSurface, ByVal Color As Long) As cCairoSurface
Dim CC As cCairoContext, TmpSrf As cCairoSurface
'we have to do this in two steps (because HSL-Operations do not support Alpha)
Set CC = Cairo.CreateSurface(Src.Width, Src.Height).CreateContext
CC.Paint 1, Cairo.CreateSolidPatternLng(vbBlack)
CC.RenderSurfaceContent Src, 0, 0
CC.Operator = CAIRO_OPERATOR_HSL_COLOR
CC.Paint 1, Cairo.CreateSolidPatternLng(Color)
Set TmpSrf = CC.Surface 'store the result of Step 1 in a Tmp-Surface
'Ok, now step 2 (Masking of the TmpSrf with the original Src)
Set CC = Cairo.CreateSurface(Src.Width, Src.Height).CreateContext
CC.SetSourceColor Color
CC.MaskSurface Src
CC.SetSourceSurface TmpSrf
CC.MaskSurface Src
Set ApplyHueTo = CC.Surface
End Function
It produces these results (from a GreyScale-Alpha-Source):
Attachment 184993
Edit: added a Project-Zip -> Attachment 184995
HTH
Olaf
-
1 Attachment(s)
Re: My Potions are too strong for you Traveller. Cairo Hue Shift?
Hi Olaf,
I was getting the similar results with a basic Operator = CAIRO_OPERATOR_HSL_SATURATION to my original picture. (Because it already has colour tones in it, which allows the hue shift.)
The reason for Hue 'Shift', and not 'Hue Overwrite' is to preserve the 'other' colours present in the original.
For example, if I add a yellow tint to your red potion bottle original, the tint vanishes to a single colour.
Seen here, the red/yellow bottles' lower incarnations are flat. Not the desired result.
Attachment 184997
It means brown beer bottles with golden highlights, or an orange potion with an inky purple seeping in become flat too. This is what was happening with the very first autobuilder, now scrapped.
I'll continue on the hue shift integration in a few days when I'm better rested. :)
-
Re: My Potions are too strong for you Traveller. Cairo Hue Shift?
Olaf's solution seems to require a greyscale base image, not one with colour. Is there some reason you can't start the "hue shifting" process with a greyscale image? Look at his code, it seems it is not so much changing the hue of the image as it is performing a blend operation of the grayscale image onto a coloured background. Such an approach would be a tad bit unpredictable if you start with a coloured image.
-
Re: My Potions are too strong for you Traveller. Cairo Hue Shift?
Shouldn't the bottle and cap or stopper be one image, and the "potion" contents another?
Then after tinting and adjusting saturation and brightness of the contents, first render the contents and then render the transparent bottle in front of it? A little crude and requires that the bottle be flat-on to the eye so its bottom renders as just a thick line... but at least the glass and stopper don't end up tinted or brightness distorted and you don't get any awkward tinted "glow."
If the ultimate goal is a transparent PNG the canvas should be all transparent pixels before rendering I suppose.
I think all of this can be done with plain old GDI32 calls (including loading the source PNG images as bitmaps)... except encoding the result in PNG format. Much of the heavy lifting could be done using SetColorAdjustment().
As a bonus this can all be done using DDBs and compatible DCs. That way GDI Scaling can be used to keep your UI from falling apart under High DPI (even multimonitor mixed DPI).
-
Re: My Potions are too strong for you Traveller. Cairo Hue Shift?
Ok, I'm wrong. StretchBlt() does not preserve the alpha channel even for a 32bpp DC and Bitmap so SetColorAdjustment() is not available.
Spoke too soon. It is true but there is a hack around it. I already have to loop over the bitmap bits to premultiply the alpha anyway.
-
3 Attachment(s)
Re: My Potions are too strong for you Traveller. Cairo Hue Shift?
Attachment 185000
Here's a quick breakdown of the potion assembly. Note, you must NOT start with a greyscale image. That is forbidden! :eek:
Puh! Dirty Hobbitses and their greasyscales!
Attachment 185001
There are so many tonal colours in the solution that it's too much work to recreate in Cairo from a greyscale.
Basically, I make a huge bottle at 600px^2 and use Photoshop layering effects to get what I want(what I think looks coolest). Basically, that initial bottle body is just a white blob of pen strokes and fill, Photoshop does the illumination, gradients, tone, colour variance on the fly. (Again, thanks to it's Layering Effects and proficiency. *Smug Smug*) So if I want a new bottle, I only draw a white blob shape. Same with all the other components leather, neck, stopper, insignia.
Those layers are then re-assembled on Cairo, with many stoppers, leather, bodies, necks and so on. Unlimited Potion Works.
All randomly chosen, same as the Cairo Rock Builder.
But, I do want the bottle contents to have a full spectrum colour array. Normally one uses hue shifting as it doesn't interfere with the white glass reflect or outline, that's critically (artistically) important.
Hence why I'm tracking it down, but I'm on massive loads of painkillers today, so I'm just falling asleep at the keyboard instead. :cry:
Thankfully, I've got the code prepped and ready to input to use RGB separated layers which ultimately ends up in the same as what hue shifting does.
Before all of that, I run some specialised automations through Photoshop to produce the potion bottle components with further lighting etc, and that's a whole other potion bottle of fishsauce.
Attachment 185003 Fishsauce takes no time to draw, less than a moment.
So, greyscale starting image is BAD! Begone wicked thoughts of monotoness! Foul demoness!
-
Re: My Potions are too strong for you Traveller. Cairo Hue Shift?
I think exploring Tanner Helland's PhotoDemon is an excellent idea.
However, I just think of hue shifting as a RyGcBmRyGcBm... circle (red-yellow-green-cyan-blue-magenta-red...). If we imagine our three RGB pixel values (0 to 255), and think of a sum of them, it's just rotating those values in a way that keeps their sum the same, gradually shifting which is higher and which is lower, etc.
I suppose the differentials (between the RGB values) must also stay the same, or it just all goes to gray.
-
Re: My Potions are too strong for you Traveller. Cairo Hue Shift?
Yeah, it sounds like tinting isn't the goal at all. Probably colorspace rotation shifting each pixel's hue by the same amount in a circular manner.
-
Re: My Potions are too strong for you Traveller. Cairo Hue Shift?
Quote:
Originally Posted by
dilettante
Yeah, it sounds like tinting isn't the goal at all. Probably colorspace rotation shifting each pixel's hue by the same amount in a circular manner.
I strongly suspect this as well.
I'm currently examining the the code Olaf posted to try and figure out how to reproduce my VB.Net sample in VB6 using RC6's Cairo objects which does exactly as you said, rotates the hue of the image. This is the same strategy I used in the PixelPainter application I also mentioned in this thread. It's basically a stripped down version of GIMP's Colourize feature. It's typically used to recolour sprites and such for games. For example if you have sprites of a guard in red uniform, you can shift the hues to change the colour of the uniform to say, green or brown.
I'll post that when I'm done. I have to kind of feel my way around Cairo by trial and error because RC6's implementation of Cairo is not documented. A lot of guess work but I'm making progress.
-
1 Attachment(s)
Re: My Potions are too strong for you Traveller. Cairo Hue Shift?
Try this:-
https://www.youtube.com/watch?v=UXkBoWHNRg4
I've finally been able to figure out a bit about using Cairo thanks to the code Olaf posted earlier.
The above demonstrates a VB6 version of the VB.Net version I posted earlier. This one uses Cairo and a translated version of the VB.Net code to perform hue shifting. See attachment for the application.
-
2 Attachment(s)
Re: My Potions are too strong for you Traveller. Cairo Hue Shift?
Niya, reading your code is like....
Attachment 185012
Not the hue shift I was looking for. *Finger motion*. Carry on.
Attachment 185013
Meanwhile, the Methstar is nearing completion.... R G B are now in separate folders. Photoshop automations are all complete. I just need to go sleep and deal with the nested multiple file loading crap again.
-
Re: My Potions are too strong for you Traveller. Cairo Hue Shift?
Quote:
Originally Posted by
-Corso->
:D Yea it was very painful doing that in VB6 to be honest. It took me like 20 to 30 minutes to do the VB.Net version and it took me nearly all a day to do that VB6 version. I kept getting side tracked by VB6's various limitations because I'm no longer used to them. Plus I had to do a lot of trial and error to try and guess my way through Cairo.
Quote:
Originally Posted by
-Corso->
Based on that image, it works exactly as I expected. What's wrong with it?
-
1 Attachment(s)
Re: My Potions are too strong for you Traveller. Cairo Hue Shift?
Attachment 185015
Ok, to explain, that slider function has overwritten all tones in the image when activated. It's 'looks' like a hue shift functionally speaking, but it actually overwrites first, then your slider hue shifts. So the image was overpainted really. Which is what the first autobuilder and Olaf's version does.
The picture below, blue bottle is what true hue shifting is. Notice the darker blue liquid near the top? If I scroll the hue shift slider in Photoshop, it maintains the 'other' variant colours. And the others are there for showing it further. So, really speaking, no overpaint, actual 'shift'.
It's tricky, but I was hoping Cairo had some sort of inbuilt function for sliding colours, but doesn't look like it.
-
Re: My Potions are too strong for you Traveller. Cairo Hue Shift?
Ak ok. I think I know what you want. I might need to make some minor changes to how the hue is applied. I can't promise it would achieve the effect you want but I'm willing to give it a try.
Can you provide me with an image of original bottle by itself?
-
2 Attachment(s)
Re: My Potions are too strong for you Traveller. Cairo Hue Shift?
Very happy to encourage users back to VB6. :D
Attached are some rough PNG's. Normally I'd remove the leather but it doesn't matter in this instance. Techgnome's link has the RGB HSV conversion code. So I should really concentrate on that. But various painkillers are making my brain mush.
I think it's just a matter of going over each pixel, pulling it's R,B,G values, convert those to HSV via Techgnome's link, adjusting the H value by a set amount, then converting back to RGB, then writing over the original surface/image.
I'd have to dig up my BindToArray code once more....
(Is this how one attaches images here???)
-
2 Attachment(s)
Re: My Potions are too strong for you Traveller. Cairo Hue Shift?
Ok, here's my working code for a Cairo Surface shift.
Just feed it any surface and give it a 0 to 255 hue shift amount.
Attachment 185018
BUT: Stick in this guy's modules before you do: https://www.vbforums.com/showthread....RGB-conversion
THANK YOU BEN321 from Jan 19th, 2015, 08:13 PM. Your excellent quality service has been recognized!
Code:
Sub Hue_Shift_Me(My_Surface As cCairoContext, ByVal Hue_Shift_Amount As Single)
'-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
' Hue Shift a Surface
'-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
'This sub hue shifts an surface by a set amount. Note Hue is 0 to 255 max.
Dim Pixel_Height As Long 'Height of the surface
Dim Pixel_Width As Long 'Width of the surface
Pixel_Height = My_Surface.Surface.Height 'Write down their sizes
Pixel_Width = My_Surface.Surface.Width
Dim My_Connection() As Byte 'This is the bound array connection to the surface so we can extract and write pixel data
Dim C As Integer 'Counter
Dim D As Integer 'Counter
Dim Hue As Byte
Dim Value As Byte
Dim Saturation As Byte
Dim Red As Byte: Dim Green As Byte: Dim Blue As Byte 'Our wanted pixel colours
Dim Trim_Amount As Integer
'[BIND SURFACE TO OPERATIONL ARRAY]
My_Surface.Surface.BindToArray My_Connection 'Conenct the surface for input and output
'Let's scan through all the pixels to extract R, G & B values
For D = 0 To (Pixel_Height - 1) 'To the full image height
For C = 0 To (Pixel_Width - 1) * 4 Step 4 'To the full image width. In byte form, we need to skip over some data (alpha)
Blue = My_Connection(C + 0, D)
Green = My_Connection(C + 1, D)
Red = My_Connection(C + 2, D)
'Now that we have R,G,B, we can convert that to a hue
'If it's all zero's neglect it
If Blue <> 0 Or Red <> 0 Or Green <> 0 Then
'Call Colour_Shift(Red, Green, Blue, Hue_Shift_Amount)
Call RGBtoHSV(Red, Green, Blue, Hue, Saturation, Value)
'Add the hue shift
If (Hue + Hue_Shift_Amount) > 255 Then 'If over, use the excess as the new value
Trim_Amount = Hue + Hue_Shift_Amount - 255
Hue = Trim_Amount
Else
Hue = Hue + Hue_Shift_Amount 'Standard add which doesn't go over 255
End If
Call HSVtoRGB(Hue, Saturation, Value, Red, Green, Blue)
'Over write the hue shift
My_Connection(C + 0, D) = Blue
My_Connection(C + 1, D) = Green
My_Connection(C + 2, D) = Red
End If
Next C
Next D
My_Surface.Surface.ReleaseArray My_Connection 'Release the array
End Sub
And now the Methstar has been destroyed!
Attachment 185019
Ok, will update with pictures when I gets me arts done.
-
2 Attachment(s)
Re: [RESOLVED] My Potions are too strong for you Traveller. Cairo Hue Shift?
Attachment 185020
Ahhhhh it's working now. Fancy a little tiddly wink there guvenar!
I tweaked the saturation in the code too. You just overwrite the Saturation value to a new random one.
Attachment 185021
-
Re: [RESOLVED] My Potions are too strong for you Traveller. Cairo Hue Shift?
FWIW, here is my take at HSV-Routines (best placed in a *.bas Module):
Code:
Public Sub RGB2HSV(ByVal R As Byte, ByVal G As Byte, ByVal B As Byte, H As Long, S As Single, V As Single)
If G > R Then H = G - R: V = G Else H = R - G: V = R
If B > V Then H = B - V + H: V = B Else If V - B > H Then H = V - B
If V = 0 Then S = 0 Else S = H / V: V = V / 255
Select Case CByte(V * 255) 'return H Between 0 and 360 (S and V between 0 and 1)
Case R: If H Then H = 60 * ((0 + G - B) / H + 0): If H < 0 Then H = H + 360
Case G: If H Then H = 60 * ((0 + B - R) / H + 2)
Case B: If H Then H = 60 * ((0 + R - G) / H + 4)
End Select
End Sub
Public Sub HSV2RGB(ByVal H As Long, ByVal S As Single, ByVal V As Single, R As Byte, G As Byte, B As Byte)
Dim i As Long, X As Long
For i = 1 To 5 Step 2
X = (H + i * 60 + 360000) Mod 360: If X >= 180 Then X = 240 - X
If X < 0 Then X = 0 Else If X > 60 Then X = 60
If i = 5 Then R = V * (1 - S * X / 60) * 255
If i = 3 Then G = V * (1 - S * X / 60) * 255
If i = 1 Then B = V * (1 - S * X / 60) * 255
Next
End Sub
The above pair operates (native-compiled) about factor 20 faster than what Niya has produced.
And here's a function, which does Hue-Rotation (also to be placed in a *.bas):
Code:
Public Function HueRotate(Src As cCairoSurface, ByVal HueAngle_PlusMinus360 As Long, _
Optional ByVal SatIntervalMin As Single, Optional ByVal SatIntervalMax As Single = 1, _
Optional ByVal LumIntervalMin As Single, Optional ByVal LumIntervalMax As Single = 1) As cCairoSurface
Dim P() As Byte, X As Long, Y As Long, H As Long, S As Single, V As Single
Set HueRotate = Src.CreateSimilar(, , , True) 'make a copy of the source
Cairo.DeMultiplyAlpha HueRotate.DataPtr, HueRotate.Stride * HueRotate.Height
HueRotate.BindToArray P
For Y = 0 To UBound(P, 2): For X = 0 To UBound(P, 1) Step 4 '<- notice Step4 (Byte-Order in P is "BGRA")
RGB2HSV P(X + 2, Y), P(X + 1, Y), P(X + 0, Y), H, S, V
If S >= SatIntervalMin And S <= SatIntervalMax Then
If V >= LumIntervalMin And V <= LumIntervalMax Then
HSV2RGB H + HueAngle_PlusMinus360, S, V, P(X + 2, Y), P(X + 1, Y), P(X + 0, Y)
End If
End If
Next X, Y
HueRotate.ReleaseArray P
Cairo.PreMultiplyAlpha HueRotate.DataPtr, HueRotate.Stride * HueRotate.Height
End Function
Please note the enclosing of the Pixel-Loop between "De- and Pre-Multiply-Alpha" calls (on the Result-Surface).
It's important to expand the RGB-Values to their "full-range" first (before doing HSL or HSV manipulations) -
...the final PreMultiply will ensure proper Alpha-Channel-corresponding RGB-Values before routine-exit.
Also note the Optional Filter-Params for Saturation and Luminance (if you leave them out, you will have a "Standard-Hue-Shift").
Ok, Form-Test-Code for all that:
Code:
Option Explicit
Private Src As cCairoSurface
Private Sub Form_Load()
Caption = "Press a MouseButton, and Move the Mouse"
Set Src = Cairo.ImageList.AddImage("", App.Path & "\potion_orig.png", 128, 128)
Set Picture = Src.Picture
End Sub
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
HTH
Olaf
-
Re: [RESOLVED] My Potions are too strong for you Traveller. Cairo Hue Shift?
Yea, go with Olaf's version. It's way better than what I posted.
However, I'd be curious to know if what he posted above works for you. The reason I ask is because based on what you posted about the results you expected, there is something else I wanted to try.
-
1 Attachment(s)
Re: [RESOLVED] My Potions are too strong for you Traveller. Cairo Hue Shift?
Here is a quick and dirty test that uses GDI32. No GDI+, no Cairo, no add-in libraries at all.
It seems to be close to what we're talking about here. The main limitation is that it doesn't have as "Save as PNG" option for tweaked images, which would require the use of some library (GDi+, etc.) since GDI32 has no PNG encoder I'm aware of. Another limitation is that it requires Windows Vista or later: it can't run on Altair Basic or Windows XP. ;)
Bonus: It copes with High and even Per Monitor DPI on Windows 10 (version 1703 Creator's Update) or later. No coding hoops jumped through, it relies on the appcompat option "GDI Scaling."
Easy to test, unzip the archive. Then copy the two images above into the Project folder ("Bottle Yellow Green.png" and "Bottle Light.png"). Runs in the IDE, or better as a compiled EXE.
Probably a bit crude, I just wanted to see what I could get quickly.
-
2 Attachment(s)
Re: [RESOLVED] My Potions are too strong for you Traveller. Cairo Hue Shift?
Oh nice Job Dilettante. That works nicely! There's a man who knows his potion bottles. And a swift drink to you!
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
And now the fun begins...
Attachment 185028
More alcohol than a Dwarven Brewery coming up.
-
Re: [RESOLVED] My Potions are too strong for you Traveller. Cairo Hue Shift?
Quote:
Originally Posted by
dilettante
Here is a quick and dirty test that uses GDI32. No GDI+, no Cairo, no add-in libraries at all.
It seems to be close to what we're talking about here. The main limitation is that it doesn't have as "Save as PNG" option for tweaked images, which would require the use of some library (GDi+, etc.) since GDI32 has no PNG encoder I'm aware of. Another limitation is that it requires Windows Vista or later: it can't run on Altair Basic or Windows XP. ;)
Bonus: It copes with High and even Per Monitor DPI on Windows 10 (version 1703 Creator's Update) or later. No coding hoops jumped through, it relies on the appcompat option "GDI Scaling."
Easy to test, unzip the archive. Then copy the two images above into the Project folder ("Bottle Yellow Green.png" and "Bottle Light.png"). Runs in the IDE, or better as a compiled EXE.
Probably a bit crude, I just wanted to see what I could get quickly.
I can't get your sample to work on my PC:-
Code:
Case vbString
F = FreeFile(0)
Open PngData For Binary Access Read As #F
ReDim PngBytes(LOF(F) - 1)
Get #F, , PngBytes
Close #F
It crashes at the line in red with a "subscript out of range" error. I checked the value of LOF(F) and it returned 0 which suggested to me that it wasn't finding the file. I attempted a fix by prepending App.Path but for some reason it still doesn't work. LOF(F) still returns 0 which means it's still not finding the file. My VB6 is still rusty in many areas so I'm wondering if it has anything to do with the actual path of the image:-
Code:
D:\New VB6 Stuff\AAA Experiments with HSB, RGB HSL etc\GDI Potion Blender\Bottle Yellow Green.png
I'm wondering if VB6's open statement is having trouble with that path somehow.
EDIT:
NVM. I think I found the problem.
EDIT:
Yea, I found the problem. The PNG file was corrupted somehow. It was 0 bytes in length. I just had to re-download the image. The program works now.
-
Re: [RESOLVED] My Potions are too strong for you Traveller. Cairo Hue Shift?
Quote:
Originally Posted by
-Corso->
There's a man who knows his potion bottles.
Well, thanks. But if you saw the ones I tried to draw myself you might die from laughing or crying.
No artist here! And I was working with stone knives and bearskins (MS Paint, MS Paint 3D, IrfanView, and some quickly-hacked together WIA scripts).
-
Re: [RESOLVED] My Potions are too strong for you Traveller. Cairo Hue Shift?
Quote:
Originally Posted by
Niya
I'm wondering if VB6's open statement is having trouble with that path somehow.
Could be. A quick workaround might be to load the data via ADODB.Stream instead, since it accepts a Unicode file path.
Ahh, good to see you resolved the issue.
-
Re: [RESOLVED] My Potions are too strong for you Traveller. Cairo Hue Shift?
Looking at Dilettante's program, I'm starting to think that HSL would have been a better colour space than HSB. My PixelPainter app also uses HSL and it produces similar results. The only difference is that Dilettante's code somehow avoids rotating the grays at the bottle cork, the logo on the bottle and the grey lighting to the left-bottom of the bottle. PixelPainter on the other hand would rotate everything. However, in my app, specific pixels could be selected and when I select only the contents of the bottle, avoiding the grey areas, it produces the same output as Dilettante's program. Long story short, HSL seems to produce better results than HSB.
@Dilettante.
I also notice in your code, you only allow hue rotations of 240 degrees. Why not the full 360?
Also, how does your code avoid rotating the greys? If I select all pixels in my pixel painter app, this is the result:-
https://www.vbforums.com/images/ieimages/2022/06/2.png
As you can see, everything is shifted yet in your code I can't readily tell how the greys are being avoided without manual intervention. What's the insight?
-
Re: [RESOLVED] My Potions are too strong for you Traveller. Cairo Hue Shift?
Those ShLwAPI calls only use 0-240 for the 3 elements even though 16-bit WORD arguments are used. Weird, hmm?
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.
-
Re: [RESOLVED] My Potions are too strong for you Traveller. Cairo Hue Shift?
I see I have some leftover junk from early testing too. For example:
Code:
Private Sub Draw()
Dim ScaleBy As Long
Dim DrawW As Long
Dim DrawH As Long
Two variables are declared but no longer used and can be deleted.
There are probably a few more goofs and artifacts of playing, and little attempt was made at optimization.
The key to being "safe for GDI Scaling" is to avoid DIBs and use DDBs wherever possible. DIBs do not get automagically scaled.
Found another gaffe from tinkering:
Code:
For I = 0 To BitBytesCount - 1 Step 4
BitBytes(I + 3) = BitBytes(I + 3)
Alpha = BitBytes(I + 3)
If Alpha = 0 Then
BitBytes(I) = 0
BitBytes(I + 1) = 0
BitBytes(I + 2) = 0
Else
Now it's getting embarrassing. But that one came from an early experiement where there were two arrays thee.
-
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?