Changing alpha of rgb bit - java

I am setting alpha of rgb of buffredimage in java.
This code changes alpha value but i can't retrieve the same value after saving the file.
How to overcome this problem.
// ================ Code for setting alpha ===============
int alpha=140;
// alpha value to set in rgb
int b=alpha<<24;
b=b|0x00ffffff;
ialpha.setRGB(0, 0,ialpha.getRGB(0, 0)&b);
// ialpha is a bufferedimage of type TYPE_INT_ARGB
ImageIO.write(ialpha, "png", new File("C:/newimg.png"));
System.out.println("\nFile saved !");
// ================ Code for getting alpha ===============
int val=(ialpha.getRGB(0, 0)&0xff000000)>>24;
if(val<0)
val=256+val;
System.out.println("Returned alpha value:"+val);
This just returns 255 as alpha value. it does not return value i set i.e 140.
Please help me to retrieve alpha value i previously set.

The problem is in the code for getting the alpha. In the second bit shift operation, you don't take the sign bit into consideration.
int val=(ialpha.getRGB(0, 0) & 0xff000000) >> 24;
This will give the value 0xffffff8c (given your initial alpha of 140 of 0x8c).
See Bitwise and Bit Shift Operators for more detail. In particular:
The unsigned right shift operator ">>>" shifts a zero into the leftmost position, while the leftmost position after ">>" depends on sign extension.
You need to either do either:
int val = (ialpha.getRGB(0, 0) & 0xff000000) >>> 24; // shift zero into left
Or:
int val = ialpha.getRGB(0, 0) >> 24) & 0xff; // mask out the sign part
PS: I tend to prefer the latter, because most people (myself included) never remember what the >>> operator actually does.. ;-)

Related

More efficient way to blend pixels (semi-transparency)?

I'm working on drawing semi-transparent images on top of other images for a small 2d game. To currently blend the images I'm using the formula found here: https://en.wikipedia.org/wiki/Alpha_compositing#Alpha_blending
My implementation of this is as follows;
private static int blend(int source, int dest, int trans)
{
double alpha = ((double) trans / 255.0);
int sourceRed = (source >> 16 & 0xff);
int sourceGreen = (source >> 8 & 0xff);
int sourceBlue = (source & 0xff);
int destRed = (dest >> 16 & 0xff);
int destGreen = (dest >> 8 & 0xff);
int destBlue = (dest & 0xff);
int blendedRed = (int) (alpha * sourceRed + (1.0 - alpha) * destRed);
int blendedGreen = (int) (alpha * sourceGreen + (1.0 - alpha) * destGreen);
int blendedBlue = (int) (alpha * sourceBlue + (1.0 - alpha) * destBlue);
return (blendedRed << 16) + (blendedGreen << 8) + blendedBlue;
}
Now, it works fine, but it has a pretty high overhead since it's being called for every single pixel every single frame. I get a performance drop of around 30% FPS as opposed to simply rendering the image without blending.
I just wanted to know if anyone can think of a better way to optimise this code as I'm probably doing too many bit operations.
not a java coder (so read with prejudice) but you are doing some things really wrong (from mine C++ and low level gfx perspective):
mixing integers and floating point
that requires conversions which are sometimes really costly... Its much better to use integer weights (alpha) in range <0..255> and then just divide by 255 or bitshift by 8. That would be most likely much faster.
bitshifting/masking to obtain bytes
yes its fine but there are simpler and faster methods simply by using
enum{
_b=0, // db
_g=1,
_r=2,
_a=3,
};
union color
{
DWORD dd; // 1x32 bit unsigned int
BYTE db[4]; // 4x8 bit unsigned int
};
color col;
col.dd=some_rgba_color;
r = col.dd[_r]; // get red channel
col.dd[_b]=5; // set blue channel
decent compilers could optimize some parts of your code to this internally on its own but I doubt it can do it everywhere...
You can also use pointers instead of union in the same way...
function overhead
you got function blending single pixel. That means it will be called a lot. its usually much faster to blend region (rectangle) per single call than call stuff on per pixel basis. Because you trash the stack this way. To limit this you can try these (for functions that are called massively):
Recode your app so you can blend regions instead of pixels causing much less function calls.
Lower the stack trashing by lowering operands, return values and internal variables of called function to limit the amount of RAM being allocated/freed/overwritten/copied each call... For example by using static or global variables for example the Alpha will most likely not be changing much. Or you can use alpha encoded in the color directly instead of having alpha as operand.
use inline or macros like #define to place the source code directly to code instead of function call.
For starters I would try to recode your function body to something like this:
enum{
_b=0, // db
_g=1,
_r=2,
_a=3,
};
union color
{
unsigned int dd; // 1x32 bit unsigned int
unsigned char db[4]; // 4x8 bit unsigned int
};
private static unsigned int blend(unsigned int src, unsigned int dst, unsigned int alpha)
{
unsigned int i,a,_alpha=255-alpha;
color s,d;
s.dd=src;
d.dd=dst;
for (i=0;i<3;i++)
{
a=(((unsigned int)(s.db[i]))*alpha) + (((unsigned int)(d.db[i]))*_alpha);
a>>=8;
d.db[i]=a;
}
return d.dd;
}
However if you want true speed use GPU (OpenGL Blending).

Reading Little Endian – LS Byte first for integer how to ignore the extra 0

I have been reading these byte by bytes from streams. Example I read this line like this.
int payloadLength = r.readUnsignedShort();
The problem I have is that 2 bytes value is x3100 so it turns out to be 12544 but I suppose to only read as x31 which makes it to be only 49. How to ignore the extra 00.
Right shift the value by 8 bits and then and it with 0xFF. Right shifting moves the bits 8 bits to the right. Any other bits would also be moved to the right so you need to mask those of by do an ANDing (&) with 0xFF to get rid of them.
int payloadLength = r.readUnsignedShort();
payloadLength = (payloadLength >>> 8)& 0xFF;
System.out.println(payLoadLength);
You may also want to swap the two bytes.
v = 0xa0b;
v = swapBytes(v);
System.out.println(Integer.toHexString(v)); // 0xb0a
public static int swapBytes(int v) {
return ((v << 8)&0xFF00) | ((v >> 8) & 0xFF);
}
Normally, for reading in just 16 bits you would not have to and it with 0xFF since the high order bits are 0's. But I think it is a good practice and will prevent possible problems in the future.

Having trouble converting integer color for cyan to RGB

There is a simple algorithm to convert integer values to RGB value of three numbers between 0-255 at integer to rgb. I got the integer number from Android Colors. I even ran:
System.out.println(Color.decode("-16711681"));
and the answer was java.awt.Color[r=0,g=255,b=0], which is expected.
I literally have an issue on step one, -16711681 % 256 is 255, and I expect 0 for the red color. In Java I coded:
System.out.println(-16711681 % 256);
and I get -1, which means I have to add 256 and my red color is 255. Can someone help me?
That's because your number is not an ABGR-packed int like your link to gamedev suggests, but an ARGB-packed int.
the Color.decode(int) wants a color in the following format:
0xAARRGGBB
where AA is the transparency, RR is the red, GG is the green, and BB is the blue. When you execute color % 256, that returns the blue (BB) portion of the color.
If we look at the color with Integer.toHexString(-16711681), we get:
Color: ff00ffff
(Format: AARRGGBB)
Which is equivalent to Color[r=0,g=255,b=255]
If you want to read the red value, you need to shift it over first:
(color >> 16) & 0xFF
Lets say x=-16711681
The Binary value of x is 11111111000000001111111111111111
Integer c = new Integer(-16711681);
System.out.println(Integer.toBinaryString(x));
Now, according to Java Docs to get the Red Value we need to extract 16-23 bits from x
Qn: How do i extract 8 bits from Positions 16-23 out of a 32 bit Integer?
Answer: x = (x >> 16) & 0xFF;
// Bits 24-31 are alpha, 16-23 are red, 8-15 are green, 0-7 are blue
Hence, Color.decode("-16711681")); is equivalent to
System.out.println(((-16711681 >> 16) & 0xFF) + ":"
+ ((-16711681 >> 8) & 0xFF) + ":" + ((-16711681 >> 0) & 0xFF));
Output
0:255:255
Note that
System.out.println(Color.decode("-16711681")); outputs
java.awt.Color[r=0,g=255,b=255]

How to modify the alpha of an ARGB hex value using integer values in Java

I'm working on a project that allows a user to adjust the alpha of a color using a custom slider. The slider returns an integer from 0-255 that defines the new alpha value the user wishes to use.
The problem is that the colors have to be in hexadecimal, and I don't know how to convert the 0-255 integer into a hexadecimal integer that can modify the original ARGB hexadecimal. I have done a little research (Like "How would one change the alpha of a predefined hexadecimal color?"), but nothing I found could fix my problem. I thought about using the Color class from java AWT, however, it doesn't have a getRGBA() method.
What I want to happen:
/**
* Original ARGB hexadecimal
* Alpha: 255, Red: 238, Blue: 102, Green: 0
*/
int originalColor = 0xFFEE6600;
/**
* Creates a new hexadecimal ARGB color from origColor with its alpha
* replaced with the user's input (0-255)
* EX: If userInputedAlpha = 145 than the new color would be 0x91EE6600
*/
int newColor = changeAlpha(origColor, userInputedAlpha);
All I need is the changeAlpha method, which modifies the color parameter's alpha (which is a hexadecimal integer) with the user inputed alpha (which is an integer from 0-255)
You know that the alpha value is stored in the bits 24 to 31, so what you can do is to apply first a mask to drop the previous alpha value and then shift the one the user inputted to apply it to the color.
int changeAlpha(int origColor, int userInputedAlpha) {
origColor = origColor & 0x00ffffff; //drop the previous alpha value
return (userInputedAlpha << 24) | origColor; //add the one the user inputted
}
Which can be easily reduced to a one liner:
return (origColor & 0x00ffffff) | (userInputedAlpha << 24);
It seems that you were perturbed about the fact that the values are in hexadecimal or not. An integer is an integer, hexadecimal is just a notation. After all there's only 0 and 1 in our computers.

Removing lowest order bit

Given a binary number, what is the fastest way of removing the lowest order bit?
01001001010 -> 01001001000
It would be used in code to iterate over the bits of a variable. Pseudo-code follows.
while(bits != 0){
index = getIndexOfLowestOrderBit(bits);
doSomething(index);
removeLowestOrderBit(bits);
}
The possible languages I'm considering using are C and Java.
This is what I've got so far, I'm wondering if anyone can beat this.
bits &= bits-1
Uh ... In your example, you already know the bit's index. Then it's easy:
bits &= ~(1 << index);
This will mask off the bit whose index is index, regardless of its position in the value (highest, lowest, or in-between). Come to think of it, you can of course use the fact that you know the bit is already set, and use an XOR to knock it clear again:
bits ^= (1 << index);
That saves the inversion, which is probably one machine instruction.
If you instead want to mask off the lowest set bit, without knowing its index, the trick is:
bits &= (bits - 1);
See here for instance.
You can find the lowest set bit using x & (~x + 1). Example:
x: 01101100
~x+1: 10010100
--------
00000100
Clearing the lowest set bit then becomes x & ~(x & (~x + 1)):
x: 01101100
~(x&(~x+1)): 11111011
--------
01101000
Or x & (x - 1) works just as well and is easier to read.
The ever-useful Bit Twiddling Hacks has some algorithms for counting zero bits - that will help you implement your getIndexOfLowestOrderBit function.
Once you know the position of the required bit, flipping it to zero is pretty straightforward, e.g. given a bit position, create mask and invert it, then AND this mask against the original value
result = original & ~(1 << pos);
You don't want to remove the lowest order bit. You want to ZERO the lowest order SET bit.
Once you know the index, you just do 2^index and an exclusive or.
In Java use Integer.lowestOneBit().
I don't know if this is comparable fast, but I think it works:
int data = 0x44A;
int temp;
int mask;
if(data != 0) { // if not there is no bit set
temp = data;
mask = 1;
while((temp&1) == 0) {
mask <<= 1;
temp >>= 1;
}
mask = ~mask;
data &= mask;
}

Categories

Resources