15 bits or 16 bits in Photoshop CS

JL
Posted By
Jerry_Lodriguss
Jul 4, 2004
Views
1825
Replies
58
Status
Closed
Is Photoshop CS working in a true 16 bits now, or is it still cheating with 15 bits like in Photoshop 7?

Jerry

How to Improve Photoshop Performance

Learn how to optimize Photoshop for maximum speed, troubleshoot common issues, and keep your projects organized so that you can work faster than ever before!

CC
Chris_Cox
Jul 4, 2004
It isn’t cheating, and it is still 0..32768

(otherwise it would be a lot slower and trickier to use some of the blend modes)
JL
Jerry_Lodriguss
Jul 5, 2004
Hi Chris,

Thanks for the answer.

Ok, it’s not cheating.

It’s just mis-representing the truth when Adobe calls it "Comprehensive 16-bit support."

🙂

Jerry
CC
Chris_Cox
Jul 5, 2004
It is the truth – Photoshop uses 16 bits.

It’s just not the range that some people would assume for 16 bit images.
RH
r_harvey
Jul 5, 2004
It isn’t cheating, and it is still 0..32768

32767? Isn’t that the same as 0x7fff
CC
Chris_Cox
Jul 5, 2004
No, I said 32768.
RH
r_harvey
Jul 5, 2004
0x8000?

So, if it’s unsigned, the high bit is only used to extend the range from 0-32767 all the way to 0-32768?

If it’s (twos-complement) signed, 32767+1 = -32768; I dunno, maybe there’s an absolute value in there when the calculation is done.

In either case, the high bit is still used only to extend the maximum value from 32767 to 32768. And by using that bit like that, you’ve lost its use as an overflow-catcher.
JL
Jerry_Lodriguss
Jul 5, 2004
Hi Chris,

I’m sorry I mis-understood then. My apologies.

So if there are 32768 discrete steps of tone to work with, that is a full 16 bits, isn’t it?

Jerry
RH
r_harvey
Jul 5, 2004
No, that’s still 15 bits… somehow.

"The Nobel Prize in mathematics was awarded yesterday to a California professor who has discovered a new number. The number is "bleen," which he says belongs between six and seven."

– George Carlin
J
johnkissane3
Jul 5, 2004
Way too much information.
JL
Jerry_Lodriguss
Jul 6, 2004
So what are they doing, skipping every other tone?

Jerry
RH
r_harvey
Jul 6, 2004
So if there are 32768 discrete steps of tone to work with, that is a full 16 bits, isn’t it?

Values 0-32767 would be 32768 discrete steps. However, in post #1, Chris Cox says that there are values 0-32768, which would be 32769 discrete steps. Off-by-one errors are so very common in programming; even more common than people using signed pointers.

I suppose they could shift it left one bit for calculations, to give it more range, then shift it right again when they’re done with it. Still, once that bit is shifted off, you’re back at 15-bits.

So what are they doing, skipping every other tone?

They’re skipping bleen… and most likely zero or 32768.
JL
Jerry_Lodriguss
Jul 6, 2004
Blucko
JS
John_Slate
Jul 6, 2004
Chris has said before that it is basically 15 bit+1 in order to make 50% fall directly on a value, instead of between values, as it does in 8 bit.

Exactly how you do 15 bit+1 is beyond me, but r_ could explain I’m sure.
RH
r_harvey
Jul 6, 2004
Exactly how you do 15 bit+1 is beyond me, but r_ could explain I’m sure.

I guess I could make up some sort of rationalization, but it wouldn’t be a very good one. No matter how I try, it sounds kind of silly.
CC
Chris_Cox
Jul 8, 2004
r_harvey – it’s not off by one, it is 0..32768.

That gives you a true middle value, maps a lot better to interpolated tables, simplifies a lot of the math (since we can use shifts instead of divides) and still prevents a lot of overflows.
JL
Jerry_Lodriguss
Jul 8, 2004
Chris,

Are there 32768 individually discrete levels or not?

Jerry
CC
Chris_Cox
Jul 8, 2004
Again, it is 0..32768

That means 32769 discrete levels.
JL
Jerry_Lodriguss
Jul 8, 2004
Chris,

Thanks,

Jerry
RH
r_harvey
Jul 8, 2004
That gives you a true middle value, maps a lot better to interpolated tables, simplifies a lot of the math (since we can use shifts instead of divides) and still prevents a lot of overflows.

So it really does use 0x8000, but not 0x8002 or 0x8234. And, 32768 is not devined from any computer-based storage unit, but an arbitrary value, which could just as easily be 33000, 40000, 65535. It’s just a number grabbed out of the air… and perhaps the worst possible number available in 16-bit integers–it’s the only 16-bit value (and its complement) that cannot be negated, and it is zero- or sign-extended incorrectly by many compilers.

Somehow, because 50% of 256 is 128, there has to be a parity in 16-bits… but wait, 50% is actually 127.5. It doesn’t work in either 8- or 16-bits.

It’s not an off by one error, but much larger than that–you’re using the sign bit just to represent a single value, in order to make 50% land on a whole number. Of course, every bit you add doubles the range, so you are reserving, but discarding, a whole lot of values… maybe they will appear in a later upgrade.

It would make more sense to stop at 32766, if you must have 50% work, and not waste the sign bit, or just use the whole 16-bits, because you aren’t going to get any more or less burned by the overflows, anyway. The value can’t even take advantage of CPU flags to catch unusual issues.

There’s nothing magical about shifting and rotating–it’s not even faster than dividing or adding, anymore, since it doesn’t usually pipeline. You’re already in the high bit, so if you shift at all, that bit is toast. It wouldn’t prevent overflows (which are not truly overflows, anyway, just carries or borrows).

If you’re using the result as an index, the number of values in the table should be designed around optimized fetching… like multiples of dwords or paragraphs, not 32769.

The MSVC compiler has had problems writing correct code for converting between signed and unsigned values of different sizes. Unless you’re writing in Assembly language, the compiler is likely optimizing the code to zero- or sign-extend into 32-bit registers, anyway, so there’s nothing to gain… and if you were writing in Assembly, you’d use 32-bit registers, anyway, since you would be trying to use the most efficient instructions. Of course, you can’t sign-extend, since that one lone value uses the sign bit.

I believe that what you said about grabbing 32768 out of the air was really what happened. I also believe that it was a short-sighted decision.
DM
dave_milbut
Jul 8, 2004
<random pelican in finding nemo>Nice.</pelican>
DM
dave_milbut
Jul 8, 2004
Mine.
P
PowerChild
Jul 9, 2004
Mine?
SJ
Stevie_J_V
Jul 9, 2004
He meant mate…mate. 😉
GH
Gernot_Hoffmann
Jul 9, 2004
R-Harvey,

IMO you are right. It´s just an arbitrary number.
The explanations were really not convincing.

And how is the mapping from x=0..255 to y=0..32768
by y=(32768/255)*x executed FAST without a float
operation ?

Best regards –Gernot Hoffmann
TT
Toby_Thain
Jul 9, 2004
That gives you a true middle value, maps a lot better to interpolated tables, simplifies a lot of the math (since we can use shifts instead of divides) and still prevents a lot of overflows.

LOL, that’s the ludicrous bunch of rationalisations r_harvey wanted to spare us…
GH
Gernot_Hoffmann
Jul 9, 2004
Toby,

they can convert number spaces as they like. They shouldn´t expect that somebody with thousands hours experience in
assembly programming will understand the benefits of this odd conversion.
But 15 bits are as good as 16 bits for colors. Anyway
far too accurate.

Best regards –Gernot Hoffmann
RH
r_harvey
Jul 9, 2004
And how is the mapping from x=0..255 to y=0..32768 by y=(32768/255)*x executed FAST without a float operation ?

It’s quite easy with the 80386 and later. If you want to stay the same value, but extend to 32-bits, you can copy the sign bit to the high 16-bits; if it’s unsigned, just make the high-bits zero.

To scale the number, you can use shifts. Shift 1 bit left multiplies by two… shift by 8 bits to multiply by 256, and so forth. Going smaller to larger, many values are a little dingy, so you do need to do some more massaging if you want it to look the same.

While little has changed in integers since the early ’90s, SIMD instructions have evolved quickly–and since they’re related to floating point, it has also improved.

But 15 bits are as good as 16 bits for colors. Anyway far too accurate.

It’s better to discard unnecessary information, than to wish you had it, later.

I presume Chris Cox is the messenger, not the inventor of that 32768-thing; I did not attack him. This sort of thing has happened here before, and he has said that I don’t understand, so we’ll assume that I still don’t.
CC
Chris_Cox
Jul 9, 2004
Toby:

No, those are not rationalizations. Those are facts.

If we used 0..32767, then multiplying two values (and renormalizing to the same range) would involve a divide by 32767.
If we used 0..65535, then we would have to use a divide by 65535. Both of those could be done using a reciprocal multiply – but that’s still relatively slow. Using 0..32768, we can divide by 32768 – which is just a shift, and quite fast.

Please, do try the math before making silly comments.
CC
Chris_Cox
Jul 9, 2004
As for 0..255 -> 0..32768:

result = (32768 * x + 127) / 255 = ( (x << 15) + 127) / 255

Then you can use a reciprocal multiply to replace the divide, and if you’re really good you can combine the left shift and the reciprocal calculation to speed it up further and still get the correct result (and enable it to be vectorized for AltiVec and SSE2).
DM
dave_milbut
Jul 9, 2004
jeez, this is better than wimbleton!
RH
r_harvey
Jul 9, 2004
…would involve a divide by 32767

Which is a shift.

…we would have to use a divide by 65535.

Which is another shift.

… / 255

Which is yet another shift.

That was the point of this thing… using standard machine units, powers of two and all that, makes it so easy to do things.
CC
Chris_Cox
Jul 9, 2004
r_harvey – if you think that dividing by 32767 is a shift, you need to go back to school.

Ditto for dividing by 255 – it is NOT a shift.

Powers of two DO make it easy. That’s one of the reasons we use 0..32768 instead of 0..32767 or 0..65535.
RH
r_harvey
Jul 9, 2004
you need to go back to school.

Thank you ever so much. I wrote my first Assembly language programming library in 1984, and my last Assembly language floating point one in 1997. I’m sure you’re ever so much brighter than I.

However, if you do calculations using the normal POWERS OF TWO, the shifts work.

I guess it was your idea to use 32768. I can’t imagine any other reason you would be defending it so.
CC
Chris_Cox
Jul 9, 2004
255 is not a power of two, 32767 is not a power of two, and 65535 is not a power of two.

256, 32768, and 65536 are powers of two.

Dividing by 32767 cannot be done with a single shift.
Dividing by 32768 can be done with a single shift.
CC
Chris_Cox
Jul 9, 2004
It wasn’t my idea – I’m just explaining the reasons.
DM
Don_McCahill
Jul 10, 2004
Re: jeez, this is better than wimbleton!

Yeah Dave, but then watching the grass grow is better than Wimbleton.

<gd&r>
J
johnkissane3
Jul 10, 2004
Still, too much information.
GH
Gernot_Hoffmann
Jul 10, 2004
(Chris Cox):
As for 0..255 -> 0..32768:
result = (32768 * x + 127) / 255 = ( (x << 15) + 127) / 255 ———————————————————–

This operation uses intermediate numbers which exceed the destination number space: 32768*x or x<<15 .

It works with 32-bit numbers but that´s IMO not a clean programming style.

Best regards –Gernot Hoffmann
RH
r_harvey
Jul 10, 2004
It works with 32-bit numbers but that´s IMO not a clean programming style.

They’re all 32-bit numbers while they’re in the CPU (soon to be 64-bit numbers). You can’t multiply 32768 by anything larger than one, and expect the result to fit in 16-bits. I would be shocked if they were doing 16-bit calculations, using 16-bit registers. Besides, the choice of magic numbers was apparently not based on what fits snugly in registers.
GH
Gernot_Hoffmann
Jul 10, 2004
And what´s the state of the art for MMX/SIMD technology for the four parallel pipelines: 16 or 32 bit each ?

Best regards –Gernot Hoffmann
JS
John_Slate
Jul 10, 2004
<Uncle Jed Online> Whee doggies! Thars a powerful heap of cipherin’ a goin’ on in this here thread! </UJO>
DE
david_evanson
Jul 10, 2004
That’s what I like about Math – no ambiguity in the answers, its either right or wrong. Well that’s what I thought until I started following this thread. Can’t wait for the sequel – 64 Bits… Photoshop Reloaded. LOL
RH
r_harvey
Jul 10, 2004
And what´s the state of the art for MMX/SIMD technology for the four parallel pipelines: 16 or 32 bit each ?

Fluxing nicely. Nowhere near capacity.

SIMD stuff (which includes MMX) often works with multiple chunks of data, at the same time. The instructions don’t add anything that you couldn’t do by hand, one chunk at a time, but they streamline the process. You don’t need a co-processor to do floating point, either, but the manual way is much uglier.

By the way, when talking about powers of two, all numbers are not powers of two. They’re regular old numbers, just like anywhere else. What you do is pick units that work well on the hardware.
CC
Chris_Cox
Jul 11, 2004
Gernot – AltiVec and SSE2 can work with 8, 16 or 32 bit integers. (16, 8 or 4 at a time in a 128 bit register)
JW
Jim_Wattes
Jul 18, 2004
I am trying to figure out what is going on too.
In 16-bit mode if you create a pixel that is pure while 0xFFFF(65535) the Info pallet displays 32768 and the value passed into the plug-ins is 32768 in fact all pixels values passed into a plug-in are 15 bit values. They all need to be They all need to be multiplied by 2 on the way in and divided by 2 on the way out. Surly this is a bug.

Jim Watters
jimwattersATrogersDOTcom
L
LenHewitt
Jul 18, 2004
Jim,

all pixels values passed into a plug-in are 15 bit values.<<

15-bits encompasses 0-32767

Photoshop uses 0-32768. That requires 16 bits.

Read the answers from Chris Cox in this topic
TT
Toby_Thain
Jul 18, 2004
this is a bug

Arguably yes, given that Photoshop claims to be able to work with 16-bit/channel images. It cannot; rather, the quasi-15-bit range you describe. But the official Adobe position seems to be that this is a feature, and not a bug. They insist black and blue it’s faster to work with 0..32768 than 0..65535.

I am sure they are working hard on more flexible (and wider) channel types for a future Photoshop version. When that’s ready, no doubt they’ll change their tune to: "now you really *do* need full 16/32/whatever bits/channel, so upgrade".
CC
Chris_Cox
Jul 19, 2004
Jim – read what has already been written.

It is not a bug, and it is not 15 bits.
CC
Chris_Cox
Jul 19, 2004
Toby – it’s not that we "insist", but it is an easily verifiable FACT that it is still faster to work with 0..32768 than with 0..65535 for image processing tasks like those done in Photoshop.
TT
Toby_Thain
Jul 20, 2004
it is still faster to work with 0..32768 than with 0..65535 for image processing tasks like those done in Photoshop

So it has been asserted, but the supporting arguments are barely credible. No actual benchmarks have been presented in terms of slowdown and I seriously doubt, on modern processors, that it is measurable at all.
If 0..32768 is "not 15 bits", it certainly isn’t 16 bits either. What do you suggest we call it? 15.01 bits?
TT
Toby_Thain
Jul 20, 2004
it is still faster to work with 0..32768 than with 0..65535 for image processing tasks like those done in Photoshop

So it has been asserted, but the supporting arguments are barely credible. No actual benchmarks have been presented in terms of slowdown and I seriously doubt, on modern processors, that it is measurable at all. The only technical argument attempted has concerned 16-bit multiplies, and those are used in only a tiny subset of Photoshop operations, in any case.

If 0..32768 is "not 15 bits", it certainly isn’t 16 bits either. What do you suggest we call it? 15.01 bits?

The elephant in the room remains: Photoshop’s "16-bit" ain’t 16-bit.
JW
Jim_Wattes
Jul 20, 2004
Chris – Sorry, new to this form, did not realize there were other replys hidden.

I under stand now why use use this range. Thank you.

I was confused because I was retrieving the values through the plug-in interface writing them to a file and then opening the file is PS. The resulting image would be two time too dark.

Now the plug-in up samples the pixels to 0 to 0xFFFF so the image can be manipulated and saved. But what is going to happen when the plug-in is used with other graphic apps?

the resulting image is saved and opened because PS does not allow a plug-in to resize an image.

Jim
CC
Chris_Cox
Jul 20, 2004
Toby – I can’t give out Photoshop code. You can write the benchmarks yourself, and just the fact that I can use shifts instead of divides is a 30:1 speedup!

Jim – check the SDK documentation. For some of the plugin APIs you can tell Photoshop to scale the data (one way or the other). Since the Photoshop SDK specifies that 16 bit/channel data is in 0..32768 format — all other apps hosting Photoshop plugins must use that format.

Yes, the only way to resize the canvas is via automation plugins (or some clever event handling, but I don’t recommend that).
DM
Don_McCahill
Jul 20, 2004
Maybe an analogy will explain things together. If I have a 7 seat van, and drive in it with only 6 people, does that make it a 6 seat van?

The number 32768 is the largest used by PS … and it uses 16 bits. So how can one claim that it is a 15 process.

I for one am not willing to see filters operate 30 times slower in order to have another 32767 levels of color (or whatever) when the human eye cannot detect such minute changes in level. (My eyes cannot even detect the differences at 256 levels, although I know some people claim to be able to do so).
JS
John_Slate
Jul 20, 2004
I for one am not willing to see filters operate 30 times slower in order to have another 32767 levels of color (or whatever) when the human eye cannot detect such minute changes in level. (My eyes cannot even detect the differences at 256 levels, although I know some people claim to be able to do so).

Here, here!

And that being said, true 15bit would certainly provide more than enough levels of gray for anybody, so even if 0…32768 is deemed to be less than 16bit who the he** cares?
TT
Toby_Thain
Jul 20, 2004
just the fact that I can use shifts instead of divides is a 30:1 speedup

It has been pointed out before that shifts are exactly the same arithmetic operation (and equally useful, and equally fast) whether your range is 0..32768 or 0..65535 or in fact any binary representation.

To imply that you are achieving a 30 x speedup by using the shorter range (yes, 1 bit shorter) is absurd.

To those who wonder if there is a visible difference: I’m not suggesting there is. But some uses need transparent processing of 16 bit data. If you simply open and re-save a 16-bit file, you will lose 1 significant bit from your data. (That’s why I call it quasi-15-bit.)

In a perfect world, Adobe would admit the deficiency, instead of calling a spade a camel; and we would be spared the string of embarrassing rationalisations which are irrelevant 15 years after Photoshop was architected for much older processors (68000) which had more restricted and slower arithmetic instructions.
CC
Chris_Cox
Jul 21, 2004
Toby – and I corrected you on your bad math.
Shifts are only the same when you are dividing by an exact power of 2.

65535 is not a power of 2.
255 is not a power of 2.

Yes, a divide is close to 30 cycles, and a shift is normally 1 cycle.

I’m telling you the way things really are.

If you have a problem with reality, you should take that up with your psychiatrist.
SJ
Stevie_J_V
Jul 21, 2004
Ouch!

Subtle and personal.

How to Master Sharpening in Photoshop

Give your photos a professional finish with sharpening in Photoshop. Learn to enhance details, create contrast, and prepare your images for print, web, and social media.

Related Discussion Topics

Nice and short text about related topics in discussion sections