Convert a N-Bytes to a Float defined by the Q-Number - java

Is there an easy way to convert a byte array of N bytes to a float defined by the Q-Number.
In 2's Compliment (Forgot To mention this before)
Example: 0xFFF0 -> Float-point using a s3.12 Q-Number
https://en.wikipedia.org/wiki/Q_(number_format)

Following suggestion by Peter Lawrey:
private static void test(short x) {
float y = (float)(x & 0x7FFF) / (1 << 12);
if ((x & 0x8000) != 0)
y = -y;
System.out.printf("%04x: %g%n", x, y);
}
Test
test((short)0xFFF0);
test((short)0xFFFF);
test((short)0x0000);
test((short)0x0001);
test((short)0x1000);
test((short)0x9000);
test((short)0x7FFF);
Output
fff0: -7.99609
ffff: -7.99976
0000: 0.00000
0001: 0.000244141
1000: 1.00000
9000: -1.00000
7fff: 7.99976

You can use
byte[] bytes = ....
ByteBuffer bb = ByteBuffer.wrap(bytes).order(ByteOrder.????); // check your byte order
while(bb.remaining() > 1) {
short s = bb.getShort();
boolean signed = s < 0;
int value = s & 0x7FFF;
double d = s / 4096.0;
if (signed)
d = -d;
System.out.println(d);
}

Related

Can i use bytes which in decimal have negative values as positive values

If i have these methods as below :
public int add (int a , int b) {
assert(a>= 0 && a < 256 && b >= 0 && b < 256);
// the addition is simply an xor operation in GF (256) since we are working on modulo(2) then 1+1=0 ; 0+0=0; 1+0=0+1=1;
return a ^ b;
}
The second method is:
public int FFMulFast(int a, int b){
int t = 0;;
if (a == 0 || b == 0)
return 0;
// The multiplication is done by using lookup tables. We have used both logarithmic and exponential table for mul
// the idea is firstly look to Logarithmic table then add their powers and find the corresponding of this to exponential table
t = (Log[(a & 0xff)] & 0xff) + (Log[(b & 0xff)] & 0xff);
if (t > 255) t = t - 255;
return Exp[(t & 0xff)];
}
Now i want to use these methods for calculating polynomial f(x)=a0+a1x + a2 x (pow 2) + ... a2 x (pow k-1) where these coefficients a0 , a1 , a2 i have generated as below :
public void generate (int k) {
byte a [] = new byte [k];
Random rnd = new SecureRandom () ;
a.nextBytes (a); // the element of byte array are also negative as for example -122; -14; etc
}
Now i want to calculate my polynomial but i am not sure if it works because of this negative coefficients . I know JAVA supports only signed bytes but i am not sure if the method below will work properly :
private int evaluate(byte x, byte[] a) {
assert x != 0; // i have this x as argument to another method but x has //only positive value so is not my concern , my concern is second parameter of //method which will have also negative values
assert a.length > 0;
int r = 0;
int xi = 1;
for (byte b : a) {
r = add(r, FFMulFast(b, xi));
xi = FFMulFast(xi, x);
}
return r;
}
Any suggestion please? Also if this one is not working can anyone suggest me how to turn negative values to positive ones without using masking because then it will be changed data type to int and then i cant use getBytes(a) method
for (byte b : a) {
r = add(r, FFMulFast(b, xi));
xi = FFMulFast(xi, x);
}
If the add() and FFMulFast() methods expect positive values, you will have to use:
for (byte b : a) {
r = add(r, FFMulFast(b & 0xff, xi));
xi = FFMulFast(xi, x & 0xff);
}

Converting bytes to int

In my project I need to open the SEQ file, so I use FileInputStream, it requires to load data to byte array. But because of that each pixels get wrong value (cause they are Integers).
Below in my code you can see that i put pixels in 2d array and for that I count each value of pixel, in line:
wart =(int) (buf[offset]) +(int)(buf[offset+1]) * 255;
I know that values because of byte input format are wrong (first two pixels aka double should be 152,109692453756 and 152,068644316116 but in my Java function they get -2474, -690)
I tried using the mask:
wart =(int) (buf[offset]<< 8) & 0x0000ff00 +(int)(buf[offset+1])& 0x000000ff * 255 ;
it helps a little (values arent negative, but they are "shifted" too much (first two pixels 19456, 18944)
I don't know how to solve this problem. I know that the mask should be different, but I don't know how to set it.
public class Sekwencja2 {
#SuppressWarnings("empty-statement")
public double[] sekwencja2(String nazwa,int nr_klatki) throws FileNotFoundException, IOException{
InputStream is = null;
DataInputStream dis = null;
is = new FileInputStream(nazwa);
dis = new DataInputStream(is);
int length = dis.available();
byte[] buf = new byte[length];
dis.readFully(buf);
int l_klatek = ((length-158864)/158864)+1;
int width = 320;
int height = 240;
int C1=21764040;
double C2=3033.3;
double C3=134.06;
int z = 0;
double[] oneDArray = new double[width*height];
double [][] pixels = new double[width][height];
int offset =0;
char type;
String typeText;
type=(char)buf[0];
typeText =Character.toString(type);
switch (typeText) {
case "A":
if(nr_klatki == 1)
offset= 696;
else
offset = 158136+(nr_klatki-1)*569+(nr_klatki-2)*(320*240*2+3839);
break;
case "F":
offset=(nr_klatki-1)*158864 + 1373;
break;
}
int wart = 0 ;
for(int x = 0; x<320; x++){
for (int y = 0; y<240;y++){
switch (typeText){
case "A":
if(nr_klatki==1)
wart =(int) (buf[offset]) +(int)(buf[offset+1]) * 255;
else
wart = (int)(buf[offset]<< 8)& 0x0000ff00 +(int)(buf[offset+1])&0xff*255 ;
break;
case "F":
wart = (buf[offset]<< 8)& 0x0000ff00 +(buf[offset+1])& 0x000000ff * 255 ;
break;
}
System.out.print(", "+wart);
pixels[x][y]=wart;
offset = offset+2;
}
}
for(int i = 0; i < width; i ++)
{
System.arraycopy(pixels[i], 0, oneDArray, i * height, height);
}
return oneDArray;
}
}
I know it's a mess, a lot of things are commented :)
255 is wrong
it's 256, you always have to multiply by a multiple of the base you are operating, 255 isn't a multiple of 2
analogy:
convert 111 from base 10 to base 10 in your way
1*99 + 1*9 + 1 = 109
so 109 != 111 which is wrong, likewise multiplying by 255 will alter any number you try to convert from binary to binary.
Mask first, like this:
wart = (buf[offset] & 0xFF) | ((buf[offset+1] & 0xFF) << 8);

How to mix PCM audio sources (Java)?

Here's what I'm working with right now:
for (int i = 0, numSamples = soundBytes.length / 2; i < numSamples; i += 2)
{
// Get the samples.
int sample1 = ((soundBytes[i] & 0xFF) << 8) | (soundBytes[i + 1] & 0xFF); // Automatically converts to unsigned int 0...65535
int sample2 = ((outputBytes[i] & 0xFF) << 8) | (outputBytes[i + 1] & 0xFF); // Automatically converts to unsigned int 0...65535
// Normalize for simplicity.
float normalizedSample1 = sample1 / 65535.0f;
float normalizedSample2 = sample2 / 65535.0f;
float normalizedMixedSample = 0.0f;
// Apply the algorithm.
if (normalizedSample1 < 0.5f && normalizedSample2 < 0.5f)
normalizedMixedSample = 2.0f * normalizedSample1 * normalizedSample2;
else
normalizedMixedSample = 2.0f * (normalizedSample1 + normalizedSample2) - (2.0f * normalizedSample1 * normalizedSample2) - 1.0f;
int mixedSample = (int)(normalizedMixedSample * 65535);
// Replace the sample in soundBytes array with this mixed sample.
soundBytes[i] = (byte)((mixedSample >> 8) & 0xFF);
soundBytes[i + 1] = (byte)(mixedSample & 0xFF);
}
From as far as I can tell, it's an accurate representation of the algorithm defined on this page: http://www.vttoth.com/CMS/index.php/technical-notes/68
However, just mixing a sound with silence (all 0's) results in a sound that very obviously doesn't sound right, maybe it's best to describe it as higher-pitched and louder.
Would appreciate help in determining if I'm implementing the algorithm correctly, or if I simply need to go about it a different way (different algorithm/method)?
In the linked article the author assumes A and B to represent entire streams of audio. More specifically X means the maximum abs value of all of the samples in stream X - where X is either A or B. So what his algorithm does is scans the entirety of both streams to compute the max abs sample of each and then scales things so that the output theoretically peaks at 1.0. You'll need to make multiple passes over the data in order to implement this algorithm and if your data is streaming in then it simply will not work.
Here is an example of how I think the algorithm to work. It assumes that the samples have already been converted to floating point to side step the issue of your conversion code being wrong. I'll explain what is wrong with it later:
double[] samplesA = ConvertToDoubles(samples1);
double[] samplesB = ConvertToDoubles(samples2);
double A = ComputeMax(samplesA);
double B = ComputeMax(samplesB);
// Z always equals 1 which is an un-useful bit of information.
double Z = A+B-A*B;
// really need to find a value x such that xA+xB=1, which I think is:
double x = 1 / (Math.sqrt(A) * Math.sqrt(B));
// Now mix and scale the samples
double[] samples = MixAndScale(samplesA, samplesB, x);
Mixing and scaling:
double[] MixAndScale(double[] samplesA, double[] samplesB, double scalingFactor)
{
double[] result = new double[samplesA.length];
for (int i = 0; i < samplesA.length; i++)
result[i] = scalingFactor * (samplesA[i] + samplesB[i]);
}
Computing the max peak:
double ComputeMaxPeak(double[] samples)
{
double max = 0;
for (int i = 0; i < samples.length; i++)
{
double x = Math.abs(samples[i]);
if (x > max)
max = x;
}
return max;
}
And conversion. Notice how I'm using short so that the sign bit is properly maintained:
double[] ConvertToDouble(byte[] bytes)
{
double[] samples = new double[bytes.length/2];
for (int i = 0; i < samples.length; i++)
{
short tmp = ((short)bytes[i*2])<<8 + ((short)(bytes[i*2+1]);
samples[i] = tmp / 32767.0;
}
return samples;
}

How to correctly convert from rgb565 to rgb888

I'm trying to convert a value from rgb565 to rgb888 but I can't seem to get it right.
I've also checked a few existing answers like this one but there are values that don't seem to be properly convert.
Here's what I've tried so far:
PImage picker;
int c;
void setup(){
size(285,240);
picker = loadImage("hsv.gif");
int c = color(255,255,255);
byte[] word = colorToWord(c);
int[] rgb = wordToRGB(word);
noStroke();
fill(c);
rect(0,0,50,100);
fill(rgb[0],rgb[1],rgb[2]);
rect(50,0,50,100);
}
void draw(){
image(picker,0,0);
if((mouseX >= 0 && mouseX <= picker.width)&&
(mouseY >= 0 && mouseY <= picker.height)) c = picker.get(mouseX,mouseY);
byte[] word = colorToWord(c);
int[] rgb = wordToRGB(word);
// int[] rgb = rgbWordToRGB(word);
int cc = color(rgb[0],rgb[1],rgb[2]);
fill(c);
rect(0,159,142,80);
fill(cc);
rect(142,159,143,80);
fill(0);
text("original\n"+hex(c),10,185);
text("converted\n"+hex(cc),152,185);
}
byte[] colorToWord(int c){
int r = (c >> 16) & 0xFF;
int g = (c >> 8) & 0xFF;
int b = c & 0xFF;
return new byte[]{(byte)((r&248)|g>>5),(byte)((g&28)<<3|b>>3)};
}
int[] wordToRGB3(byte[] data){
// Reconstruct 16 bit rgb565 value from two bytes
int rgb565 = (data[0] & 255) | ((data[1] & 255) << 8);
// Extract raw component values (range 0..31 for g and b, 0..63 for g)
int b5 = rgb565 & 0x1f;
int g6 = (rgb565 >> 5) & 0x3f;
int r5 = (rgb565 >> 11) & 0x1f;
// Scale components up to 8 bit:
// Shift left and fill empty bits at the end with the highest bits,
// so 00000 is extended to 000000000 but 11111 is extended to 11111111
int b = (b5 << 3) | (b5 >> 2);
int g = (g6 << 2) | (g6 >> 4);
int r = (r5 << 3) | (r5 >> 2);
return new int[]{r,g,b};
}
int[] wordToRGB2(byte[] word){
int r = word[0]&248;
int g = (word[0]<<5) | ((word[1]&28)>>3);
int b = word[1] << 3;
r <<= 3;
g <<= 2;
b <<= 3;
return new int[]{r,g,b};
}
int[] wordToRGB(byte[] word){
int c = (word[0] << 8) | (word[1]);
//RGB565
int r = (c >> (6+5)) & 0x01F;
int g = (c >> 5) & 0x03F;
int b = (c) & 0x01F;
//RGB888 - amplify
r <<= 3;
g <<= 2;
b <<= 3;
return new int[]{r,g,b};
}
final int RGB565_MASK_RED = 0xF800;
final int RGB565_MASK_GREEN = 0x07E0;
final int RGB565_MASK_BLUE = 0x001F;
int[] rgbWordToRGB(byte[] word){
int rgb565 = (word[0] << 8) | (word[1]);
int[] rgb24 = new int[3];
rgb24[2] = (rgb565 & RGB565_MASK_RED) >> 11;
rgb24[1] = (rgb565 & RGB565_MASK_GREEN) >> 5;
rgb24[0] = (rgb565 & RGB565_MASK_BLUE);
//amplify the image
rgb24[2] <<= 3;
rgb24[1] <<= 2;
rgb24[0] <<= 3;
return rgb24;
}
using this image as a colour palette:
The problem is with certain values:
Why does that happen ? Is there a way to fix that ?
ok so here's the fix if I understand correctly:
in your wordToRGB() method replace the first line:
int c = (word[0] << 8) | (word[1]);
with
int c = (word[0] << 8) | (word[1] & 0xFF);
The problem happens when you convert from byte to int. Example 1:
int a = 255;
println(binary(a));
int b = (byte) 255;
println(binary(b));
prints:
00000000000000000000000011111111
11111111111111111111111111111111
Example 2:
int a = 127;
println(binary(a));
int b = (byte) 127;
println(binary(b));
prints:
00000000000000000000000001111111
00000000000000000000000001111111
Processing pads with to the left with whatever your last bit was, so essentially after that, your | distorts all the values.
>> is arithmetic shift, so it will sign extends the value. Use logic shift >>> instead
In C, there's no >>> operators, the right shift depends on implementation but most will do a logical shift if the variable is unsigned, so just cast or define it as unsigned

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