Ken Warner wrote:
> Well, I did a test.  The double shift does clamp the top end.  But negative
> numbers are twisted to be 255.  In bi-cubic interpolation (the reason
> for all
> this nonsense) negative byte (channel) values can occur. The goal is to
> clamp to the range [0-255] so -100 goes to 0 and 300 goes to 255.
>
> Here's the snippet:
>
> //        sum = (s1[s1PixelOffset]&0xFF) + (s2[s2PixelOffset]&0xFF);
> //        d[dPixelOffset] = (byte)((((sum<<23) >> 31) | sum) & 0xFF);
>
>        int foo = 0;
>        int bar = 0;
>        for(int i = -10; i < 265; i++)
>        {
>            foo = i;
>            bar = ((((foo << 23) >> 31) | foo) & 0xFF);
>
>            System.err.println(i + ": foo = " + foo + ", bar = " + bar );
>
>        }
>

int >> 31 will fill the int with the most significant bit, because of
sign extension. That will give you either 0 or -1.

The <<23 drops everything except the least significant 9 bits off the
high end. That leaves bit 8 ( the ninth bit ) in the most significant
bit position, aka the sign bit. In the original code, an addition is
performed on two byte values, masked to 8 bits. This effectively
converts the byte values to unsigned. The highest bit that can be set by
such an addition is bit 8. When this bit is set, the shifts will give
-1, which OR'd with the original value will give -1, thence 255 when
masked by 0xFF.

How are you generating the values? It looks as though the values, before
calculation, are unsigned. If so, you might try this:

       int foo = 0;
       int bar = 0;
       for(int i = -10; i < 265; i++)
       {
           foo = i;
           bar = (((((foo << 23) >> 31) | foo) & ~(foo>>31))&0xFF);
           //                                   ^ this is a "not"
           //                       Thunderbird is sucking mightily

           System.err.println(i + ": foo = " + foo + ", bar = " + bar );
       }

Basically, take the previous result, but override when the sign is
negative (foo>>31);

The question remains, is it worthwhile?

Peter

> And here is the abbreviated output:
> -4: foo = -4, bar = 255
> -3: foo = -3, bar = 255
> -2: foo = -2, bar = 255
> -1: foo = -1, bar = 255
> 0: foo = 0, bar = 0
> 1: foo = 1, bar = 1
> 2: foo = 2, bar = 2
> 3: foo = 3, bar = 3
> 4: foo = 4, bar = 4
> .
> .
> .
> 252: foo = 252, bar = 252
> 253: foo = 253, bar = 253
> 254: foo = 254, bar = 254
> 255: foo = 255, bar = 255
> 256: foo = 256, bar = 255
> 257: foo = 257, bar = 255
> 258: foo = 258, bar = 255
> 259: foo = 259, bar = 255
>
>
>
> Finally, com.sun.media.jai.util.ImageUtil.java does this to clamp a byte
> value
> which is equivalent to what I was doing.  I need to clamp both ends
> reliably.
> I wonder if it can be done with shifts and masks?  Maybe I've done the best
> that can be done.
>
> public static final byte clampByte(int in) {
>        return (in > 0xFF ? (byte)0xFF : (in >= 0 ? (byte)in : (byte)0));
>    }
>
> Ken Warner wrote:
>> Never mind -- found it...
>>
>> http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.19
>>
>>
>>
>> At run time, shift operations are performed on the two's complement
>> integer representation of the value of the left operand.
>>
>> The value of n<<s is n left-shifted s bit positions; this is equivalent
>> (even if overflow occurs) to multiplication by two to the power s.
>>
>> The value of n>>s is n right-shifted s bit positions with
>> sign-extension. The resulting value is � n/2s⌋. For nonnegative values
>> of n, this is equivalent to truncating integer division, as computed by
>> the integer division operator /, by two to the power s.
>>
>> Now if I could only understand this...
>>
>> [EMAIL PROTECTED] wrote:
>>
>>>> if(r < 0) r = 0;
>>>> if(r > 255) r = 255;
>>>> if(g < 0) g = 0;
>>>> if(g > 255) g = 255;
>>>> if(b < 0) b = 0;
>>>> if(b > 255) b = 255;
>>>>
>>>> Clumsy and awkward.  Is there a better way to clamp
>>>> the values?
>>>> Maybe with a mask or something?
>>>
>>>
>>>
>>> If your "better" meant "faster", you might like to take a look at this:
>>> https://jai-core.dev.java.net/source/browse/jai-core/src/share/classes/com/sun/media/jai/opimage/AddOpImage.java?rev=1.1&view=markup
>>>
>>>
>>> under computeRectByte()
>>>
>>>                     //
>>>                     // The next two lines are a fast way to do
>>>                     // an add with saturation on U8 elements.
>>>                     // It eliminates the need to do clamping.
>>>                     //
>>>                     sum = (s1[s1PixelOffset]&0xFF) +
>>> (s2[s2PixelOffset]&0xFF);
>>>                     d[dPixelOffset] = (byte)((((sum<<23) >> 31) | sum)
>>> & 0xFF);
>>>
>>> HTH,
>>> -James
>>> [Message sent by forum member 'jxc' (jxc)]
>>>
>>> http://forums.java.net/jive/thread.jspa?messageID=230881
>>>


--
Peter B. West <http://cv.pbw.id.au/>
Folio <http://defoe.sourceforge.net/folio/>

===========================================================================
To unsubscribe, send email to [EMAIL PROTECTED] and include in the body
of the message "signoff JAVA2D-INTEREST".  For general help, send email to
[EMAIL PROTECTED] and include in the body of the message "help".

Reply via email to