Understanding bitwise operations on a byte array - java

I am trying to develop a program to read certain type of file and extract all the package information of this file in bit level.
The packet is divided as:
SYC: 8 bits
TEI: 1 bits
PSI: 1 bit
TP: 1 bit
PID: 13 bits
TSC: 2 bits
AFC: 2 bits
CC: 4 bits
My question is: how do I get the bits separately? For example the PID, 5 bits are in position 1 of the array and 8 bits in position 2; how can I get this information from 2 separate bytes and sum them afterwards?
I have this sample code to get the PID and it reproduces the correct result:
int PID1 = (buf [1] << 8) | (buf [2] & 0xff);
I don't understand this equation, especially buf [1] << 8. Could someone explain to me this equation and what should I do to get the rest of the package information?

The '<<' operator moves the bits position to the right in binary which is essentially the same as multiplying by two.
This code :
byte buf[] = new byte[2];
buf[1] = 3;
for (int i = 0; i < 9; i++) {
int bshifted = buf[1]<<i;
System.out.println("buf[1]<<"+i+" = " + Integer.toBinaryString(bshifted) +"(binary) = "+ bshifted + "(decimal)");
}
Produces this output:
buf[1]<<0 = 11(binary) = 3(decimal)
buf[1]<<1 = 110(binary) = 6(decimal)
buf[1]<<2 = 1100(binary) = 12(decimal)
buf[1]<<3 = 11000(binary) = 24(decimal)
buf[1]<<4 = 110000(binary) = 48(decimal)
buf[1]<<5 = 1100000(binary) = 96(decimal)
buf[1]<<6 = 11000000(binary) = 192(decimal)
buf[1]<<7 = 110000000(binary) = 384(decimal)
buf[1]<<8 = 1100000000(binary) = 768(decimal)
The whole expression (buf [1] << 8) | (buf [2] & 0xff) has the effect of moving buf[1] out of the low order 8 bits of the int and putting only the low order 8 bits of buf[2] into that part of the integer.

Related

Push 4 bits into an int in java

For an implementation of a SPN crypografic feature (studies related) I'm trying to push 4bits into an int.
I can pinpoint the mistake, but I don't know how to fix it (might stared too long at it for now).
private int applySBox(int a, boolean inverse, boolean verbose) {
// split int (16 bit) into parts of 4 bit keeping the right order
int[] parts = new int[4];
for(int i = 0; i < 4; i++) {
parts[4 - i - 1] = a & 0b1111;
a = a >> 4;
}
// Apply the SBox to each 4 bit
// E.g. 1101 traverse (enc) = 1001, inverse (dec) = 0010
for(int i = 0; i < 4; i++) {
if(inverse) {
parts[i] = sbox.inverse(parts[i]);
} else {
parts[i] = sbox.traverse(parts[i]);
}
}
int result = 0;
// put back together
for(int i = 0; i < 4; i++) {
result = parts[i] & 0b1111;
// TODO: Reassigning does not help here, needs shift and &
result = result << 4;
}
return result;
}
Before the SBox I might get a value of 1100111011001111 as cipher text.
In the split portion I get something like this:
Fragment[0]: 0001100011110000
Round Value: 0001100011110000
Current key: 1101011000111111
New r Value: 1100111011001111
---
Before SBox: 1100_1110_1100_1111
Part[0] before SBox: 1100
Part[1] before SBox: 1110
Part[2] before SBox: 1100
Part[3] before SBox: 1111
Part[0] after SBox: 1011
Part[1] after SBox: 0000
Part[2] after SBox: 1011
Part[3] after SBox: 0101
I know this is correct based on the defintion of the SBox I have to use.
This would mean, that in order to get the result I have to push parts 0 to 3 pack into one int 1011_0000_1011_0101 and it would be the correct result.
I can clearly see that it won't work because I always overwrite the result with result = parts[i] & 0b1111; I just can't seem to find a fix.
How can I push an int[] array each int with 4 bits worth of data in the order from 0 to 3 into the int result containing 16 bit of data?
If you shift the bits to the left then the rightmost bits fill up with zeros. So then you need to XOR or OR the results into place.
Try and replace
result = parts[i] & 0b1111;
with
result ^= parts[i] & 0b1111;
or
result |= parts[i] & 0b1111;
otherwise you are simply reassigning the value and delete the previous 4 bit blocks.
Do you mean:
result = (result << 4) | parts[i];
or, same thing written differently:
result |= parts[i] << (4 * (4-i));
If so then, yes, you stared too long at the screen and "got square eyes" as they say!
Update: Since OP implies it's OK to lock-in four parts. Here's an untested one-liner for the traverse variant:
return sbox.traverse(a & 0b1111)
| sbox.traverse(a >> 4 & 0b1111) << 4
| sbox.traverse(a >> 8 & 0b1111) << 8
| sbox.traverse(a >> 12 & 0b1111) << 12

Java. Extracting integers from bits in a byte array not fitting the byte boundary

I have the following array of bytes:
01010110 01110100 00100101 01001011
These bytes are broken into two groups to encode seven integers. I know that the first group consists of 3 values 4 bits each (0101 0110 0111) that represent numbers 5,6,7. The second group consists of 4 values 5 bits each (01000 01001 01010 01011), which represent integers 8,9,10, and 11.
To extract the integers, I am currently using the following approach. Convert the array into a binary string:
public static String byteArrayToBinaryString(byte[] byteArray)
{
String[] arrayOfStrings = new String[byteArray.length];
for(int i=0; i<byteArray.length; i++)
{
arrayOfStrings[i] = byteToBinaryString(byteArray[i]);
}
String bitsetString = "";
for(String testArrayStringElement : arrayOfStrings)
{
bitsetString += testArrayStringElement;
}
return bitsetString;
}
// Taken from here: http://helpdesk.objects.com.au/java/converting-large-byte-array-to-binary-string
public static String byteToBinaryString(byte byteIn)
{
StringBuilder sb = new StringBuilder("00000000");
for (int bit = 0; bit < 8; bit++)
{
if (((byteIn >> bit) & 1) > 0)
{
sb.setCharAt(7 - bit, '1');
}
}
return sb.toString();
}
Then, I split the binary string into 2 substrings: 12 characters and 20 characters. Then I split each substring into new substrings, each of which has length that equals the number of bits. Then I convert each sub-substring into an integer.
It works but a byte array representing thousands of integers takes 30 seconds to a minute to extract.
I am a bit at a loss here. How do I do this using bitwise operators?
Thanks a lot!
I assume you have an understanding of the basic bit operations and how to express them in Java.
Use a pencil to draw a synthetic picture of the problem
byte 0 byte 1 byte 2 byte 3
01010110 01110100 00100101 01001011
\__/\__/ \__/\______/\___/\______/\___/
a b c d e f g
To extract a, b and c we need to do the following
a b c
byte 0 byte 0 byte 1
01010110 01010110 01110100
\. \. |||||||| \. \.
'\ '\ XXXX|||| '\ '\
0.. 0101 0.. 0110 0.. 0111
Shift And Shift
In Java
int a = byteArray[0] >>> 4, b = byteArray[0] & 0xf, c = byteArray[1] >>> 4;
The other values d, e, f and g are computed similarly but some of them require to read two bytes from the array (d and f actually).
d e
byte 1 byte 2 byte 2
01110100 00100101 00100101
||||\\\\ | |\\\\\
XXXX \\\\ | X \\\\\
\\\\| \\\\\
0.. 01000 01001
To compute d we need to isolate the least four bits of byte 1 with byteArray[1] & 0xf then make space for the bit from byte 2 with (byteArray[1] & 0xf) << 1, extract that bit with byteArray[1] >>> 7 and finally merge together the result.
int d = (byteArray[1] & 0xf) << 1 | byteArray[2] >>> 7;
int e = (byteArray[2] & 0x7c) >>> 2;
int f = (byteArray[2] & 0x3) << 3 | byteArray[3] >>> 5;
int g = byteArray[3] & 0x1f;
When you are comfortable with handling bits operations you may consider generalizing the function that extract the integers.
I made function int extract(byte[] bits, int[] sizes, int[] res), that given an array of bytes bits, an array of sizes sizes, where the even indices hold the size of the integers to extract in bits and the odd indices the number of integers to extract, and an output array res large enough to hold all the integers in output, extracts from bits all the integers expressed by sizes.
It returns the number of integers extracted.
For example the original problem can be solved as
int res[] = new int[8];
byte bits[] = new byte[]{0x56, 0x74, 0x25, 0x4b};
//Extract 3 integers of 4 bits and 4 integers of 5 bits
int ints = BitsExtractor.extract(bits, new int[]{4, 3, 5, 4}, res);
public class BitsExtractor
{
public static int extract(byte[] bits, int[] sizes, int[] res)
{
int currentByte = 0; //Index into the bits array
int intProduced = 0; //Number of ints produced so far
int bitsLeftInByte = 8; //How many bits left in the current byte
int howManyInts = 0; //Number of integers to extract
//Scan the sizes array two items at a time
for (int currentSize = 0; currentSize < sizes.length - 1; currentSize += 2)
{
//Size, in bits, of the integers to extract
int intSize = sizes[currentSize];
howManyInts += sizes[currentSize+1];
int temp = 0; //Temporary value of an integer
int sizeLeft = intSize; //How many bits left to extract
//Do until we have enough integer or we exhaust the bits array
while (intProduced < howManyInts && currentByte <= bits.length)
{
//How many bit we can extract from the current byte
int bitSize = Math.min(sizeLeft, bitsLeftInByte); //sizeLeft <= bitsLeftInByte ? sizeLeft : bitsLeftInByte;
//The value to mask out the number of bit extracted from
//The current byte (e.g. for 3 it is 7)
int byteMask = (1 << bitSize) - 1;
//Extract the new bits (Note that we extract starting from the
//RIGHT so we need to consider the bits left in the byte)
int newBits = (bits[currentByte] >>> (bitsLeftInByte - bitSize)) & byteMask;
//Create the new temporary value of the current integer by
//inserting the bits in the lowest positions
temp = temp << bitSize | newBits;
//"Remove" the bits processed from the byte
bitsLeftInByte -= bitSize;
//Is the byte has been exhausted, move to the next
if (bitsLeftInByte == 0)
{
bitsLeftInByte = 8;
currentByte++;
}
//"Remove" the bits processed from the size
sizeLeft -= bitSize;
//If we have extracted all the bits, save the integer
if (sizeLeft == 0)
{
res[intProduced++] = temp;
temp = 0;
sizeLeft = intSize;
}
}
}
return intProduced;
}
}
Well I did the first group , the second can be done in similar fashion
public static void main(String args[]) {
//an example 32 bits like your example
byte[] bytes = new byte[4];
bytes[0] = 31;//0001 1111
bytes[1] = 54;//0011 0110
bytes[2] = 67;
bytes[3] = 19;
//System.out.println(bytes[0]);
int x = 0;
int j = -1; // the byte number
int k = 0; // the bit number in that byte
int n = 0; // the place of the bit in the integer we are trying to read
for (int i = 0; i < 32; i++) {
if (i < 12) { //first group
if (i % 8 == 0) {
j++;
k = 0;
}
if (i % 4 == 0) {
x = 0;
n = 0;
}
byte bit = (byte) ((bytes[j] & (1 << (7 - k))) >> (7 - k));
System.out.println("j is :" + j + " k is :" + k + " " + bit);
x = x | bit << (3 - n);
if ((i + 1) % 4 == 0) {
System.out.println(x);
}
k++;
n++;
} else {
}
}
}
It's a bit tricky because you are trying to encode an integer on less than what java allocates (8 bits). So I had to take each bit and "construct" the int from them
To get each bit
byte bit = (byte) ((bytes[j] & (1 << (7 - k))) >> (7 - k));
this takes the byte we are at and does And operation. For example I want the 3rd bit of the 1st byte, I do
bytes[0] & 1 << (7 - 3)
but this gives me an integer encoded over 8 bits, so I still have to shift it to get that single bit with >> (7 - 3)
Then I just Or it with x (the int we are trying to decode). All while putting it at the right position with << (3 - n) . 3 because your integer is encoded over 4 bits
Try running the code and reading the output.
I am honestly not sure if this is the best way, but I believe it's at least faster than dealing with Strings

How to fill high-end bits in a Java byte with '1' without knowing the last 1 in advance? (FAST FIX Negative Integer decoder)

I am writing a FIX/FAST decoder for negative numbers as described below:
My question is:
How to fill the high-end bits of a Java byte with 1s as it is described above? I am probably unaware of some bit manipulation magic I need to in this conversion.
So I need to go from 01000110 00111010 01011101 to 11110001 10011101 01011101.
I know how to shift by 7 to drop the 8th bit. What I don't know is how to fill the high-end bits with 1s.
It seems like the question you're asking doesn't really match up with the problem you're trying to solve. You're not trying to fill in the high bits with 1; you're trying to decode a stop-bit-encoded integer from a buffer, which involves discarding the sign bits while combining the payload bits. And, of course, you want to stop after you find a byte with a 1 in the stop bit position. The method below should decode the value correctly:
private static final byte SIGN_BIT = (byte)0x40;
private static final byte STOP_BIT = (byte)0x80;
private static final byte PAYLOAD_MASK = 0x7F;
public static int decodeInt(final ByteBuffer buffer) {
int value = 0;
int currentByte = buffer.get();
if ((currentByte & SIGN_BIT) > 0)
value = -1;
value = (value << 7) | (currentByte & PAYLOAD_MASK);
if ((currentByte & STOP_BIT) != 0)
return value;
currentByte = buffer.get();
value = (value << 7) | (currentByte & PAYLOAD_MASK);
if ((currentByte & STOP_BIT) != 0)
return value;
currentByte = buffer.get();
value = (value << 7) | (currentByte & PAYLOAD_MASK);
if ((currentByte & STOP_BIT) != 0)
return value;
currentByte = buffer.get();
value = (value << 7) | (currentByte & PAYLOAD_MASK);
if ((currentByte & STOP_BIT) != 0)
return value;
currentByte = buffer.get();
value = (value << 7) | (currentByte & PAYLOAD_MASK);
return value;
}
A loop would be cleaner, but I unrolled it manually since messaging protocols tend to be hot code paths, and there's a fixed maximum byte length (5 bytes). For simplicity's sake, I read the bytes from a ByteBuffer, so you may need to adjust the logic based on how you're reading the encoded data.
Fillig the high bits might go as:
int fillHighBits(int b) { // 0001abcd
int n = Integer.highestOneBit(b); // 00010000
n = ~n; // 11101111
++n; // 11110000
return (n | b) 0xFF; // 1111abcd
}
As expression
(~Integer.highestOneBit(b) + 1) | b
Though the examples you gave lets me doubt this is what you want.
This can be done very simply using a simple accumulator where you shift in 7 bits at a time. You need to keep track of how many bits you have in the accumulator.
Sign extension can be performed by simple logical shift left follwed by arithmetic shift right (by the same distance) to copy the topmost bit to all unused positions.
byte[] input = new byte[] { 0x46, 0x3A, (byte) 0xDD };
int accumulator = 0;
int bitCount = 0;
for (byte b : input) {
accumulator = (accumulator << 7) | (b & 0x7F);
bitCount += 7;
}
// now sign extend the bits in accumulator
accumulator <<= (32 - bitCount);
accumulator >>= (32 - bitCount);
System.out.println(Integer.toHexString(accumulator));
The whole trick is that >>N operator replicates the top bit N times.
do logical OR (|) with a number which has highend bits set to 1 and rest are 0
for example:
1010101010101010
OR 1111111100000000
--------------------
11111111101010101
something like this:
int x = ...;
x = x | 0xF000;

Java How to flip bits of an array to random values

How could you create a method that could flip 2 bits (ranges 00-11 Hence 0-3) in a byte, Randomly!
Example
Coin flip one: 111 01 111
Coin flip two: 111 11 111
Coin flip three: 111 01 111
Coin flip four: 111 10 111
What I'm working with
private static void coinFlip(byte theByte)
{
Integer mode = new Random().nextInt(3);
byte value = mode.byteValue();
byte tmp = value & 255;
tmp = tmp >> 4;
tmp = tmp & 3;
//Point of confusion
//Now stuff it back in index 5 & 4 ?
}
Based on your code:
private static byte coinFlip(byte theByte)
{
Integer mode = new Random().nextInt(3);
byte value = mode.byteValue();
return (byte)(theByte ^ (value << 3));
}
Last line is simply XORING your byte with the two shifted random bits.
Filling in using similar methods to what you are using, I think this should work:
private static byte coinFlip(byte theByte)
{
//Get random value of form 000xx000
Integer mode = new Random().nextInt(3);
byte value = mode.byteValue();
value = value << 3;
//Mask the result byte, to format xxx00xxx
byte mask = 231; //0b11100111
byte maskedByte = theByte & mask;
//return 000xx000 | xxx00xxx
return maskedByte | value;
}
As fge said, though, BitSet is the saner way to do it.
If you want to set a bit at index n, use:
b |= 1 << n;
if you want to unset a bit at index n, use:
b &= ~(1 << n);
Or use a BitSet (which has a convenient enough .flip() method).

In JAVA, what is the fastest way to convert RGB value of image to binary?

I am trying to get the RGB value of any given pixel on an image into 12 bit binary, with each channel represented by 4 bits. For example, if a pixel has it's red channel at '255', or in binary "11111111". I wish to convert that to "1111".
I have got a code working, but it is rather slow, and I am wondering if there is a better way to do this.
Here's what i did.
I use the method getRGB(x, y) to get the RGB value of one pixel.
e.g. -4278864
I convert that into 3 separate channels e.g. r 190 g 181 b 176
I divide that by 16 to get integer equivalent of 4 bit
representation
I convert the number to a binary.
Add 0's in front of the binary if the binary generated is less
than 4 bit.
Concatenate to a 12bit binary to represent 12bit color output. e.g. 101110111011
Here are my code:
import java.awt.Component;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class LoadImageApp extends Component {
private static int[] rgbArray;
private static double bitPerColor = 4.0;
public static void main(String[] args) {
BufferedImage img = null;
String fileName = "Image.jpg";
try {
//Read in new image file
img = ImageIO.read(new File("src/"+fileName));
}
catch (IOException e){
}
if (img == null) {
System.out.println("No image loaded");
}
else {
//Get RGB Value
int val = img.getRGB(500, 500);
System.out.println("rgbValue from getRGB is: " + val);
//Convert to three separate channels
int a = (0xff000000 & val) >>> 24;
int r = (0x00ff0000 & val) >> 16;
int g = (0x0000ff00 & val) >> 8;
int b = (0x000000ff & val);
System.out.println("rgbValue in RGB is: ");
System.out.println("a " + a + " r " + r + " g " + g + " b " + b);
double power = Math.pow(2.0, bitPerColor);
//Convert each channel to binary
String r4bit = Integer.toBinaryString((int)(r/(power)));
String g4bit = Integer.toBinaryString((int)(g/(power)));
String b4bit = Integer.toBinaryString((int)(b/(power)));
//Convert concatonate 0's in front to get desired bit count
int rDifference = (int)bitPerColor - r4bit.length();
int gDifference = (int)bitPerColor - g4bit.length();
int bDifference = (int)bitPerColor - b4bit.length();
for (int i = rDifference; i > 0; i--){
r4bit="0"+r4bit;}
for (int i = gDifference; i > 0; i--){
g4bit = "0"+g4bit;}
for (int i = bDifference; i > 0; i--){
b4bit = "0"+b4bit;}
//Concatonate three channel together to form one binary
String rgbValue = r4bit + g4bit + b4bit;
System.out.println("rgbValue in binary is: " + rgbValue);
}
}
}
It all works fine as as desired. However it's just really, really ugly, and slow, 2-3 seconds just to read one pixel. I was hoping to use the code to read a section of an image at a time, but i can imaging it taking AGES.
So any help would be very much appreciated.
Thanks in advance.
Your original code (in hex) is 0x00rrggbb. You want to convert this to 0x00000rgb. This will do it:
int rgb24 = ....;
int rgb12 = (rgb24 & 0x00f00000) >> 12 +
(rgb24 & 0x0000f000) >> 8 +
(rgb24 & 0x000000f0) >> 4;
If you wanted to "round" to the nearest color instead of truncating you could do this:
int r = (rgb24 & 0x00ff0000);
int g = (rgb24 & 0x0000ff00);
int b = (rgb24 & 0x000000ff);
r += (r >= 0x00f00000) ? 0x00080000 : 0;
g += (g >= 0x0000f000) ? 0x00000800 : 0;
b += (b >= 0x000000f0) ? 0x00000008 : 0;
int rgb12 = (r & 0x00f00000) >> 12 + (g & 0x0000f000) >> 8 + (b & 0x000000f0) >> 4;
This rounds up but only if the high-order 4 bits are not already 1111 (when you would risk overflow).
There are a few things that might be slowing it down, such as...
Getting each pixel individually from the BufferedImage
Using Math.pow() and possibly Integer.toBinaryString(), multiple times in the loop
Using Strings all the way through, rather than numbers like int or short. If you want a String, maybe do a single conversion from short --> String at the end.
I would probably try to do something like this...
// Get all the pixels
int pixelCount = imageWidth*imageHeight;
int[] pixelArray = new int[pixelCount];
img.getRGB(0,0,imageWidth,imageHeight,pixelArray,0,1);
// For storing the 4-bit data
short[] convertedArray = new short[pixelCount];
// calculate the conversion factor a single time
double power = Math.pow(2.0, bitPerColor);
// Loop over the pixels
for (int p=0;p<pixelCount;p++){
int pixel = pixelArray[p];
// Convert into separate channels
int a = (0xff000000 & val) >>> 24;
int r = (0x00ff0000 & val) >> 16;
int g = (0x0000ff00 & val) >> 8;
int b = (0x000000ff & val);
// Convert to 4-bit
a /= power;
r /= power;
g /= power;
b /= power;
// Create the short for the pixel (4 channels * 4 bits = a 2-byte short)
short newPixel = (a & 0x0000000f) << 24 | (r & 0x0000000f) << 16 | (g & 0x0000000f) << 8 | (b & 0x0000000f);
convertedArray[p] = newPixel;
// If you want to have the value as a String, do it here.
String binary = Short.toBinaryString(newPixel);
}
Offhand, I noticed you used the String plus operator for appending. I know it's simple code but that takes some work when it is in a loop. The operator calls a constructor to execute its function.
How big is the loop anyway?
Instead of using the plus operator, perhaps use other classes like StringBuilder or a Java equivalent of it. Tell me which class you end up using.
Investigate by timing your code!
When you want to see your possible bottlenecks, look at LOOPS in a heap or stack first since there are potentially many code executions. This should be a coding rule somewhere...
Try it out & have fun. Pls vote for my answer. I need a badge and more points :-)
Tommy Kwee
The value I have collected in the RGB when set using SetRGB will it provide me an image of binary for where the area where the image is present is white and the area whre the image is absent is black ?

Categories