|
forums.silverfrost.com Welcome to the Silverfrost forums
|
View previous topic :: View next topic |
Author |
Message |
silicondale
Joined: 15 Mar 2007 Posts: 245 Location: Matlock, Derbyshire, UK
|
Posted: Wed Mar 05, 2014 7:15 pm Post subject: Unpacking RGB colours |
|
|
Is there any library subroutine to unpack the R, G, B components of an RGB colour? This would be the inverse of the RGB@ function. I'm sure it's not too difficult to write, but I don't want to reinvent it if already available. |
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 7925 Location: Salford, UK
|
Posted: Wed Mar 05, 2014 7:46 pm Post subject: |
|
|
I don't think there is.
It will be something like the following but I have not tested this...
Code: | red = IAND(rgb, 255)
green = IAND(ISHFT(rgb,-8), 255)
blue = IAND(ISHFT(rgb,-16), 255)
|
|
|
Back to top |
|
|
silicondale
Joined: 15 Mar 2007 Posts: 245 Location: Matlock, Derbyshire, UK
|
Posted: Wed Mar 05, 2014 7:52 pm Post subject: |
|
|
That was quick! So the answer is no, but you've given me more than half the wheel to work with -- many thanks!
-Steve |
|
Back to top |
|
|
jalih
Joined: 30 Jul 2012 Posts: 196
|
Posted: Wed Mar 05, 2014 9:21 pm Post subject: |
|
|
How about something like:
Code: |
program test
integer*4 :: r, g, b
integer*4 :: i
i = Z'00FF0000'_3
call INT2RGB(i, r, g, b)
write(*,*) 'integer :', i
write(*,*) 'R:', r
write(*,*) 'G:', g
write(*,*) 'B:', b
contains
subroutine INT2RGB(int, r, g, b)
integer*4 :: int
integer*4 :: r, g, b
type rgb
union
map
integer*1 :: b, g, r, a
end map
map
integer*4 :: c
end map
end union
end type rgb
type(rgb) :: c
c%c = int
r = IAND(c%r, 255)
g = IAND(c%g, 255)
b = IAND(c%b, 255)
end subroutine INT2RGB
end program test
|
|
|
Back to top |
|
|
silicondale
Joined: 15 Mar 2007 Posts: 245 Location: Matlock, Derbyshire, UK
|
Posted: Wed Mar 05, 2014 9:56 pm Post subject: |
|
|
Many thanks, Jalih- brilliant as always !!
------------------
(edit 06/03)
Tested last night. Works fine, but I think the order it gives is b g r not r g b. Would be useful to have this as a standard library subroutine.
Last edited by silicondale on Thu Mar 06, 2014 9:22 am; edited 1 time in total |
|
Back to top |
|
|
JohnCampbell
Joined: 16 Feb 2006 Posts: 2554 Location: Sydney
|
Posted: Thu Mar 06, 2014 8:56 am Post subject: |
|
|
You can also use transfer intrinsic with an integer*1 RGB(4), being careful to check the order. Sign is a problem with integer*1. Is there a byte type ?
Not sure that map and union exist in F95 ?
John |
|
Back to top |
|
|
jalih
Joined: 30 Jul 2012 Posts: 196
|
Posted: Thu Mar 06, 2014 11:35 am Post subject: Re: |
|
|
silicondale wrote: | Works fine, but I think the order it gives is b g r not r g b. |
That's possible, I used some web based RGB to integer calculator results as a reference. Just change the order of the integer*1 variables inside the union.
JohnCampbell wrote: |
Not sure that map and union exist in F95 ?
|
You are right, the map and union constructs are language extensions. I think it's a really handy feature. |
|
Back to top |
|
|
LitusSaxonicum
Joined: 23 Aug 2005 Posts: 2388 Location: Yateley, Hants, UK
|
Posted: Thu Mar 06, 2014 1:50 pm Post subject: |
|
|
I hope that Paul will incorporate useful routines like this in the standard library in due course.
I've struggled over a related issue, but gave up (it's a very standard response of mine to a problem!) and that is automatically reducing the colour intensity while keeping recognisably the same colour. The application is basically printing an image which looks best on the screen in saturated colours. If you go to print that you get (on my inkjet) soggy areas that soak the intense colour areas and stretch all but the most expensive 'art' papers or (on my laser) make it look like the paper is covered in a layer of gloss paint that you could peel off. There's no doubt in my mind that printed images look better with less saturated colour. (Line drawings work better with saturated colours of course. I'm talking about the ones that have large areas of solid colour).
It became very obvious to me that just increasing or decreasing the r,g,b values while keeping them in the same ratio doesn't work (except for grey, when r=g=b, and even then, the perception of grey intensity is non-linear). My printers seem to work in CMYK, but the drivers accept RGB, so someone must know how to map from one to the other, but I suspect that hue, saturation, lightness is probably the easiest way to go.
Thus automatically flattening the colour would involve taking rgb, convert to hsl, tone down saturation (? - with or without increasing lightness?) and re-map to rgb for printing.
If my application only featured a few standard colours I suppose I could keep a table of the rgb values for several stages of lightening. My present solution is to encourage the user to make appropriate colour choices ab initio.
Eddie |
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 7925 Location: Salford, UK
|
Posted: Thu Mar 06, 2014 2:33 pm Post subject: |
|
|
MAP and UNION are available in FTN95 but they may not be documented. |
|
Back to top |
|
|
Wilfried Linder
Joined: 14 Nov 2007 Posts: 314 Location: Düsseldorf, Germany
|
Posted: Thu Mar 06, 2014 6:07 pm Post subject: |
|
|
If irgb is the RGB@ colour value and ired, igre and iblu are the 8-bit colour values, then
Code: | ired = iand(lobyte(loword(irgb)),255)
igre = iand(hibyte(loword(irgb)),255)
iblu = hiword(irgb)
|
can be used for instance.
Regards - Wilfried |
|
Back to top |
|
|
silicondale
Joined: 15 Mar 2007 Posts: 245 Location: Matlock, Derbyshire, UK
|
Posted: Thu Mar 06, 2014 6:28 pm Post subject: |
|
|
Eddie - I think this may help...
http://www.niwa.nu/2013/05/math-behind-colorspace-conversions-rgb-hsl/
Code: |
integer r,g,b,h,l,s
real*4 r1,g1,b1,hue,lum,sat,cmax,cmin
r1 = float(r)/255.0
g1 = float(g)/255.0
b1 = float(b)/255.0
cmin = amin1(r1,g1,b1)
cmax = amax1(r1,g1,b1)
if (cmin.eq.cmax) then
sat = 0.0
hue = 0.0
else
lum1 = int((cmin+cmax)*0.5)
if (lum.lt.0.5) then
sat = (cmax-cmin)/(cmax+cmin)
else
sat = (cmax-cmin)/(2.0-cmax-cmin)
end if
if (cmax.eq.r1) then
hue = (g1-b1)/(cmax-cmin)
else if (cmax.eq.g1) then
hue = 2.0 + (b1-r1)/cmax-cmin)
else if (cmax.eq.b1) then
hue = 4.0 + (r1-g1)/(cmax-cmin)
end if
hue = hue * 60.0
if (hue.lt.0.0) hue = hue + 360.0
if (hue.gt.360.0) hue = hue - 360.0
end if
h = ifix (hue)
l = ifix (lum)
s = ifix (sat)
|
First stab at coding it. The website gives a back conversion to RGB as well, so you can get what you want - a toned-down RGB. Come to think of it, this would be jolly useful for 'greyed' buttons where you have a coloured button.
- Steve |
|
Back to top |
|
|
jalih
Joined: 30 Jul 2012 Posts: 196
|
Posted: Thu Mar 06, 2014 8:33 pm Post subject: |
|
|
Here is a small utility for converting HSV to RGB. MiniBASIC source is included and should port easily to FTN95 if needed. |
|
Back to top |
|
|
LitusSaxonicum
Joined: 23 Aug 2005 Posts: 2388 Location: Yateley, Hants, UK
|
Posted: Thu Mar 06, 2014 11:46 pm Post subject: |
|
|
Wow,
Two answers straightaway! I'll need to experiment with how much lighter is optimum, but thanks.
Eddie |
|
Back to top |
|
|
JohnCampbell
Joined: 16 Feb 2006 Posts: 2554 Location: Sydney
|
Posted: Fri Mar 07, 2014 4:04 am Post subject: |
|
|
I think just using ishift is most straightforward.
I could not get it to break !
Code: | include <clearwin.ins>
!
real*4 x(3)
integer*4 red_i, green_i, blue_i, rgb_i, red_o, green_o, blue_o, i, error
!
do i = 1,10000000
!
! get an RGB Value
call random_number ( x )
!
red_i = int ( x(1)*256. )
green_i = int ( x(2)*256. )
blue_i = int ( x(3)*256. )
!
rgb_i = rgb@ ( red_i, green_i, blue_i )
!
call from_rgb ( rgb_i, red_o, green_o, blue_o)
!
if (i > 1) then
error = abs (red_o -red_i) + abs (green_o-green_i) + abs (blue_o -blue_i)
if (error == 0) CYCLE
write (*,*) 'ERROR : CHECK THE CONVERSION', I
end if
!
write (*,*) ' '
write (*,*) 'RGB value is',rgb_i
write (*,*) ' red is :', red_i, red_o, red_o -red_i
write (*,*) ' green is :', green_i, green_o, green_o-green_i
write (*,*) ' blue is :', blue_i, blue_o, blue_o -blue_i
end do
write (*,*) i-1,' tests'
!
end
subroutine from_rgb ( rgb_i, red_o, green_o, blue_o)
integer*4 rgb_i, red_o, green_o, blue_o
red_o = IAND (rgb_i, 255)
green_o = IAND (ISHFT(rgb_i,-8), 255)
blue_o = IAND (ISHFT(rgb_i,-16), 255)
end subroutine from_rgb
|
|
|
Back to top |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|