* Color components and fixed point numbers @ 2004-03-01 11:49 Pat 2004-03-01 16:24 ` Robert I. Eachus 0 siblings, 1 reply; 6+ messages in thread From: Pat @ 2004-03-01 11:49 UTC (permalink / raw) Hi, I would like to declare two records representing a RGB Color with two different percisions. The Small one with color components from 0..255 and the Wide one with components from 0..65535. Could I use fixed point numbers to hide the different precision: e.g. type Small_Component is delta 1/255 range 0.0 .. 1.0 type Wide_Component is delta 1/65535 range 0.0 .. 1.0 type Small_RGB is record r,g,b:Small_Component end record type Wide_RGB is record r,g,b:Wide_Component end record Then later I could use something like this to convert between the different precisions: w : Wide_RGB s : Small_RGB w.r = Wide_Component(s.r); I tried to implement this but suprisingly Wide_Component( Small_Component(1.0)) < 1.0 ? Does somebody know a workaround? Thanks, Pat ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Color components and fixed point numbers 2004-03-01 11:49 Color components and fixed point numbers Pat @ 2004-03-01 16:24 ` Robert I. Eachus 2004-03-02 10:58 ` Pat 0 siblings, 1 reply; 6+ messages in thread From: Robert I. Eachus @ 2004-03-01 16:24 UTC (permalink / raw) Pat wrote: > Hi, > > I would like to declare two records representing a RGB Color with two > different percisions. The Small one with color components from 0..255 > and the Wide one with components from 0..65535. Could I use fixed > point numbers to hide the different precision: e.g. > > type Small_Component is delta 1/255 range 0.0 .. 1.0 > type Wide_Component is delta 1/65535 range 0.0 .. 1.0 > > type Small_RGB is record > r,g,b:Small_Component > end record > > type Wide_RGB is record > r,g,b:Wide_Component > end record > > Then later I could use something like this to convert between the > different precisions: > > w : Wide_RGB > s : Small_RGB > > > w.r = Wide_Component(s.r); > > I tried to implement this but suprisingly Wide_Component( > Small_Component(1.0)) < 1.0 ? Does somebody know a workaround? No workaround is required! But I will get to that. First fix your type declarations: type Small_Component is delta 1.0/255 range 0.0 .. 1.0; type Wide_Component is delta 1.0/65535 range 0.0 .. 1.0; This may just be a problem of transcription, because I would expect a compiler to at the least give a warning for such a declaration. Besides, you also omitted the semicolons. Second, you got the numbers wrong, or you want something that many compilers would not support as a value for 'Small, even with a rep clause. You should use: type Small_Component is delta 1.0/256 range 0.0 .. 1.0; type Wide_Component is delta 1.0/65536 range 0.0 .. 1.0; Notice that for these types, a compiler is not required to represent 255.0/256 and 256.0/256 differently. In other words, a compiler is allowed to choose a representation with only 256 values, not 257. You can control this, but usually it is what you want. In fact, I would expect that you will force this representation: for Small_Component'Size use 8; for Wide_Component'Size use 16; Having done all that, you will notice that the brightest colors you can specify are different. For example, the brightest whites are: 16#FFFFFF# for Small_RGB, and 16#FFFFFFFFFFFF# for Wide_RGB. Since that is how the hardware works, that should be what you expect. So Small_RGB'(1.0,1.0,1.0) and Wide_RGB'(1.0,1.0,1.0) are different colors. Or better stated: Small_RGB(255.0/256, 255.0/256. 255.0/256) is not equal to Wide_RGB(65535.0/65536, 65535.0/65536, 65535.0/65536), and you should not expect them to be equal. Can you force an implementation to make the two brightest whites equal? It is not too difficult. Most compilers will give the expected result for: type Small_Component is delta 1.0/256 range 1.0/256 .. 1.0; type Wide_Component is delta 1.0/65536 range 1.0/65536 .. 1.0; Without any rep clauses, if that is really what you want. I could have told you this straight off. But you really need to do the thinking above to be sure you are doing the right thing, for whatever the right value of right is for you. -- Robert I. Eachus "The only thing necessary for the triumph of evil is for good men to do nothing." --Edmund Burke ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Color components and fixed point numbers 2004-03-01 16:24 ` Robert I. Eachus @ 2004-03-02 10:58 ` Pat 2004-03-02 16:39 ` Robert I. Eachus 2004-03-02 22:23 ` tmoran 0 siblings, 2 replies; 6+ messages in thread From: Pat @ 2004-03-02 10:58 UTC (permalink / raw) Thank you very much for your answer. > First fix your type declarations ... Besides, you also omitted the semicolons. Sorry, was just too lazy... > Second, you got the numbers wrong, or you want something that many > compilers would not support as a value for 'Small, even with a rep > clause. You should use: I'm very new to Ada, so what is rep clause? > Since that is how the hardware works, that should be what you expect. So > Small_RGB'(1.0,1.0,1.0) and Wide_RGB'(1.0,1.0,1.0) are different colors. > Or better stated: Small_RGB(255.0/256, 255.0/256. 255.0/256) is not > equal to Wide_RGB(65535.0/65536, 65535.0/65536, 65535.0/65536), and you > should not expect them to be equal. Yes, this is the reason why I used 255 and 65535 as denominator. I am not a expert on color conversion or representation, but I think 0.0 should represent the darkest and 1.0 the brigthest color independent from the representation as integers. So 255 and 65535 should be the same brightness. If I would use integer arithmetic I would do it like this: type Small_Comp is range 0 .. 255; type Wide_Comp is range 0 .. 65535; -- Small_Comp'Last and Wide_Comp'Last should represent the same brightest color -- Small_COmp'First and Wide_Comp'Last should represent the same darkest color w : Wide_Comp; s : Small_Comp:=?; w := s*65535 / 255; -- equals w:=s*257 s := w / 257; I though the reason why 1.0/255 is not working may be that there is no exact floating point representation of 1.0/255 and so due to rounding 255 * (1.0/255) < 1.0 . > Can you force an implementation to make the two brightest whites equal? > It is not too difficult. Most compilers will give the expected result > for: > > type Small_Component is delta 1.0/256 range 1.0/256 .. 1.0; > type Wide_Component is delta 1.0/65536 range 1.0/65536 .. 1.0; I think this will only move my problem, so that now the darkest colors are not identical. Thank you very much, Pat ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Color components and fixed point numbers 2004-03-02 10:58 ` Pat @ 2004-03-02 16:39 ` Robert I. Eachus 2004-03-02 22:23 ` tmoran 1 sibling, 0 replies; 6+ messages in thread From: Robert I. Eachus @ 2004-03-02 16:39 UTC (permalink / raw) Pat wrote: > I'm very new to Ada, so what is rep clause? Ada shorthand for representation clause, see RM 13.1 through 13.6, and elsewhere throughout the reference manual. Different rep clauses handle different aspects of a type's representation. In the case of fixed-point types, 'Small and 'Delta can both be set by rep clauses (see RM 3.5.10 http://www.adaic.org/standards/95lrm/html/RM-3-5-10.html for the attributes of a fixed-point type. The key here is 'Small which can be set by a rep clauses. (Technically by an attribute definition clause, but you can see why everyone uses the shorthand.) Why it matters is that, by default, the compiler will choose a power of two (or ten for decimal fixed-point types) as the 'Small of a type. With a rep clause you can require that the small for the type be exactly the delta for the type. Compilers can reject rep clauses that they don't support. But for 'Small compilers have gotten pretty good over the years. I have used Pi/10_000, and 1.0/1_296_000 for angle measures. (Tenth of a milliradian, and arc seconds respectively.) The Ada 95 rules made it much easier than in Ada 83 for a compiler to support such a rep clause. > Yes, this is the reason why I used 255 and 65535 as denominator. I am > not a expert on color conversion or representation, but I think 0.0 > should represent the darkest and 1.0 the brigthest color independent > from the representation as integers. So 255 and 65535 should be the > same brightness. Maybe they should, and if they did, you could write the rep clauses to force such a representation. But as I say, in all current computer hardware that I am aware of, FFFFFF is equal to FF00FF00FF00 not FFFFFFFFFFFF. Don't let that worry you though, if you look at the 'real' specifications for displays (or the NTSC or PAL broadcast rules) you will find that the actual representable color range for most monitors is much less than that. For example, if a monitor is specified as having a 500:1 constrast ratio--which is pretty good--that means that the darkest black is 1/500th of the brightest white. That means that all 24-bit colors can be distinguished (at least with measuring equipment), but usually you will run into saturation above FF80FF80FF80, and blacks below 008000800080 will not be distinguishable. (Actually you have to have a very good eye to be able to see a brightness difference of less than 5%. You might think that would make 24-bit color no different from 16-bit color (actually 15-bit color), but there are low-light levels where the differences are noticable to a trained eye. I have an Amiga that can generate an NTSC (broadcast) display signal. But if you do that you have to be aware that the brightest NTSC color is technically C0C0C0, and blacks below around 191919 should also not be used. The computer will generate those colors in NTSC mode, but technically it violates the broadcast standard. (And the NTSC signal will violate broadcast standards.) Most NTSC monitors will start having some trouble with color saturations above D0 or so. Computer monitors, though will support all the way up to FF without blooming or tearing, even if they saturate well before then. Of course they do this by clipping the analog signals. -- Robert I. Eachus "The only thing necessary for the triumph of evil is for good men to do nothing." --Edmund Burke ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Color components and fixed point numbers 2004-03-02 10:58 ` Pat 2004-03-02 16:39 ` Robert I. Eachus @ 2004-03-02 22:23 ` tmoran 2004-03-04 13:31 ` Pat 1 sibling, 1 reply; 6+ messages in thread From: tmoran @ 2004-03-02 22:23 UTC (permalink / raw) >Yes, this is the reason why I used 255 and 65535 as denominator. I am >not a >expert on color conversion or representation, but I think 0.0 should >represent >the darkest and 1.0 the brigthest color independent from the >representation as >integers. So 255 and 65535 should be the same brightness. You are expanding 8 bits into 16 bits so the question is what to use to pad out the extra 8 bits. Using 1.0/256 and 1.0/65536 pads with zeros. Declaring type Small_Comp is delta 1.0 / 255 range 0.0 .. 1.0; for Small_Comp'small use 1.0/255; for Small_Comp'Size use 8; type Wide_Comp is delta 1.0 / 65535 range 0.0 .. 1.0; for Wide_Comp'small use 1.0/65535; for Wide_Comp'Size use 16; pads with greater than zero. Note that 0.5 is then not exactly representable since 0.5*255= 127.5 I have one compiler that truncates to 7F and another that rounds to 80. In the first case doubling 0.5 will give a value less than 1.0, in the second case it's greater than 1.0 (and raises Constraint_Error), so the finiteness of the arithmetic shows up anyway. OTOH, with power-of-two deltas, neither range will include 1.0 (Small_Comp'last= 0.996 and Wide_Comp'last = 0.99609), and Small_Comp(Wide_Comp'last) will overflow. IMO, black is black, ie 00 = 0000, but "brightest" is not really fixed. Is the brightness of the screen using 8 bit color and Small_Comp'last the same as, or slightly less than, the brightness using Wide_Comp'last? And what happens if you turn up the monitor's brightness control? "1.0" is a very artifical value. As Robert Eachus pointed out, NTSC has other problems, like "blacker than black", which you may or may not have to take account of in your programming. The bottom line is that you need to make sure your graphics algorithms stay safely away from 1.0. As Robert Eachus pointed out, NTSC has other problems (like "blacker than black") so you better stay away from 0.0 also. Given those facts, the difference between a power-of-two delta and a power-of-two-minus-one is a minor point. ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Color components and fixed point numbers 2004-03-02 22:23 ` tmoran @ 2004-03-04 13:31 ` Pat 0 siblings, 0 replies; 6+ messages in thread From: Pat @ 2004-03-04 13:31 UTC (permalink / raw) tmoran@acm.org wrote > Declaring > type Small_Comp is delta 1.0 / 255 range 0.0 .. 1.0; > for Small_Comp'small use 1.0/255; > for Small_Comp'Size use 8; > > type Wide_Comp is delta 1.0 / 65535 range 0.0 .. 1.0; > for Wide_Comp'small use 1.0/65535; > for Wide_Comp'Size use 16; > > pads with greater than zero. > > Note that 0.5 is then not exactly representable since 0.5*255= 127.5 I > have one compiler that truncates to 7F and another that rounds to 80. Isn't it specified how the compiler has to round, if he has to convert a floating point constant into a fixed point value? > IMO, black is black, ie 00 = 0000, but "brightest" is not really fixed. > Is the brightness of the screen using 8 bit color and Small_Comp'last the > same as, or slightly less than, the brightness using Wide_Comp'last? And > what happens if you turn up the monitor's brightness control? "1.0" is a > very artifical value. I don't really care how at last a montior or whatever converts my color to light. I care more about the abstract value of a brightest color in color model I am using while doing calculation with the color. So often I want to convert a 8-bit color component to a 16-bit one to have more precision while doing calculations on it and afterwards I will convert it back into a 8-bit one. Anyway, thank you very much for your answers, best regards, Pat ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2004-03-04 13:31 UTC | newest] Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2004-03-01 11:49 Color components and fixed point numbers Pat 2004-03-01 16:24 ` Robert I. Eachus 2004-03-02 10:58 ` Pat 2004-03-02 16:39 ` Robert I. Eachus 2004-03-02 22:23 ` tmoran 2004-03-04 13:31 ` Pat
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox