The following code is part of a working camera app that detects motion and saves preview, painting the moving parts red.
public class RgbMotionDetection implements IMotionDetection {
that detects motion
private static final int mPixelThreshold = 50; // Difference in pixel (RGB)
private static final int mThreshold = 10000; // Number of different pixels
private static int[] mPrevious = null;
private static int mPreviousWidth = 0;
private static int mPreviousHeight = 0;
/**
* {#inheritDoc}
*/
#Override
public int[] getPrevious() {
return ((mPrevious != null) ? mPrevious.clone() : null);
}
protected static boolean isDifferent(int[] first, int width, int height) {
if (first == null) throw new NullPointerException();
if (mPrevious == null) return false;
if (first.length != mPrevious.length) return true;
if (mPreviousWidth != width || mPreviousHeight != height) return true;
int totDifferentPixels = 0;
for (int i = 0, ij = 0; i < height; i++) {
for (int j = 0; j < width; j++, ij++) {
int pix = (0xff & ((int) first[ij]));
int otherPix = (0xff & ((int) mPrevious[ij]));
// Catch any pixels that are out of range
if (pix < 0) pix = 0;
if (pix > 255) pix = 255;
if (otherPix < 0) otherPix = 0;
if (otherPix > 255) otherPix = 255;
if (Math.abs(pix - otherPix) >= mPixelThreshold) {
totDifferentPixels++;
// Paint different pixel red
first[ij] = Color.RED;
}
}
}
I'd like to understand this fully in order to be able to modify.
The line that really puzzles me is:
int pix = (0xff & ((int) first[ij]));
What does it do?
thanks
Dave
Forgive me if I explain something now that you know but I want to make this a self contained answer.
The colors of a pixel can be stored in an integer. An integer in Java consist of four bytes, a color typically (in this context) is represented with four bytes: One byte each for red, green, and blue, the last byte for transparency. The mix of the subpixels on screen results in the observed color.
So the following integer represents a color:
0 0 f f c c a a (Hexadecimal representation)
0000 0000 1111 1111 1100 1100 1010 1010 (Binary representation)
Transp.-- Red------ Green---- Blue----- (Color interpretation)
16764074 (Decimal representation, quite useless here)
In this case the first two bytes (00) represent the transparency, ff the red subpixel, cc the green, aa the blue.
If we want to get only a single part of this, e.g. the blue subpixel, we need a bit mask.
0000 0000 1111 1111 1100 1100 1010 1010 (Binary representation)
& (Binary AND: Return 1 if both bits are 1)
0000 0000 0000 0000 0000 0000 1111 1111 (Bitmask for blue, in hex 0x000000ff)
=
0000 0000 0000 0000 0000 0000 1010 1010
This is the result of the operation in the line you mention, it just uses the shorthand hex interpretation for the mask:
int pix = (0xff & ((int) first[ij]));
As the array first already is an int array the cast of first[ij] is useless.
If you want another part of the pixel, say the green part, you need to shift the mask (or use a hardcoded value) and need to shift back the result:
00ffccaa
&
0000ff00 Hardcoded, alternative: ff << 8
=
0000cc00
Shift the result to the rightmost position within the integer
0000cc00 >> 8 = 000000cc
Similar with 16 and 24 for red resp. transparency.
So the line gives you the value of the blue subpixel of the pixel. This value is in the range of 0..255, as these are the only values possible with eight bits (when interpreted as unsigned byte or stored in a Java int as it is done here; Java bytes are signed and wouldn't use that decimal representation but -128..127); any check for other values is useless here.
I think that here it tries to get the value of the pixel but in a range of 0 to 255, so it uses the mask 0xFF to delete all the bits in a higher position than 8.
But I don't understand why it uses
if (pix < 0) pix = 0;
if (pix > 255) pix = 255;
When the pix variable can't be higher than 255
Related
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
I am currently learning on bit-wise operations, and i am tasked to do a left rotate of 4-bit integer.
My code for a 4bit left rotate is
private static int BITS_IN_INTEGER = 4;
private static int leftRotate(int x, int n) {
return (x << n) | (x >> (BITS_IN_INTEGER - n));
}
I want to make a 4-bit circular shift to maintain as a 4-bit after rotating but can't seem to understand how it works.
Example: 10 (1010) after left rotate by 1 bit will give me 5 (0101) but it gives me a value of 21 which is more than my 4-bit.
Any help to make me understand this problem will be much appreciated!
If I understood you correctly, you want to
emulate integers with BITS_IN_INTEGER many bits instead of 32 bits.
do a rotation on such an emulated integer
Currently you can do a rotation, but the upper bits of the actual int which are not part of the emulated int can end up in something other than 0. Example:
intput x
0000 0000 0000 0000 0000 0000 0000 1100
|____|___, emulated int
result of rotating left by n=2 | |
0000 0000 0000 0000 0000 0000 0011 0011
As we can see, all we have to do is setting the bits above the emulated int (that is the 32 - BITS_IN_INTEGER upper bits) to zero. To this end, we use a logical "and" (&). We need a mask that has 0 on the bits we want to set to zero (anything & 0 is always 0) and a 1 on the bits we want to keep (anything & 1 is always anything).
0...0 0011 0011 ← the result from before
& 0...0 0000 1111 ← a mask
——————————————————
0...0 0000 0011 ← the masked result where unused bits are 0
To generate a mask of the form 0...01...1 with BITS_IN_INTEGER many 1s we can use (1 << BITS_IN_INTEGER) - 1. The - 1 converts 10000 into 01111.
static int BITS_IN_INTEGER = 4;
static int INTEGER_MASK = (1 << BITS_IN_INTEGER) - 1;
static int leftRotate(int x, int n) {
return INTEGER_MASK & ((x << n) | (x >>> (BITS_IN_INTEGER - n)));
}
This is a javascript implementation of leftRotate() and rightRotate(), based on the above Answer from Socowi (thank you!)
I needed to emulate a simple compass with 90º degree rotations in both left (counter-clockwise) and right (clockwise) directions (not a real compass, just a funny problem).
So instead of messing up the code by storing the previous orientation and using * if / else * or * switch *, I came up with the idea that a circular-shift or bit-rotation would be much more clean, efficient, and elegant of course.
However, I had the same problem about limiting the mask to 4 bits. Thanks to the above solution I was able to do it! ;)
So assuming the following:
- North = 1 = 0001
- West = 2 = 0010
- South = 4 = 0100
- East = 8 = 1000
When I need to turn 90º from North to -> West I call leftRotate() and so on until I get to the same point again (North).
The same applies in reverse, if turning 90º from North to -> East I call rightRotate(), and then again to turn South, and so on.
Here is the snippet, hope it helps:
const BITS_IN_INTEGER = 4;
const INTEGER_MASK = (1 << BITS_IN_INTEGER) - 1;
// this function rotates to left (counter clockwise) 1,2,4,8...1,2,4,8
function leftRotate(x, n) {
return INTEGER_MASK & ((x << n) | (x >>> (BITS_IN_INTEGER - n)));
}
// this function rotates to right (clockwise) 1,8,4,2...1,8,4,2
function rightRotate(x, n) {
return INTEGER_MASK & ((x << (BITS_IN_INTEGER - n)) | (x >>> n));
}
// Lets rotate:
console.log('--- Rotate to left (counter clockwise) 1,2,4,8...1,2,4,8...1:')
let value = 1;
for (let i = 0; i < 8; i++) {
console.log(value);
value = leftRotate(value, 1);
}
console.log('-- Rotate to right (counter clockwise) 1,8,4,2...1,8,4,2...1:')
for (let i = 0; i < 8; i++) {
console.log(value);
value = rightRotate(value, 1);
}
I'm trying make program which convert hex to decimal rgb888 and rgb565 respectively.
I’m already did my program to convert hex to rgb888 format, and my code looks like this:
String color = "0xFFFF00";
int hexToRgb = 0;
color.toLowerCase();
String[] colorSplited = color.split("0x");
String splitedConverted = colorSplited[1];
int R = Integer.valueOf(splitedConverted.substring(0,2), 16);
int G = Integer.valueOf(splitedConverted.substring(2,4), 16);
int B = Integer.valueOf(splitedConverted.substring(4,6), 16);
System.out.println(R + " " + G + " " + B);
I saw some articles where they explained that each rgb888 component R, G and B is variated by 0 and 2^8. My currently program don’t use that specific process but I got the results which I needed.
Now I need make the same program but to convert hex to rgb565,. My hex input looks like this:
String color = “0xFFE0”;
So which will be converted is FFE0.
To this input I need get the result R = 31, G = 63 and B = 0. But I have no idea how I achieve this result.
What I got in the internet was to each component RGB is variated by 0 <= R <= 2^5, 0 <= G <= 2^6 and 0 <=B <= 2^5.
Unfortunately I’m not an expert in math.
Can someone help me understand the math behind this or have any sugestions about how I can get this result?
First of all, each hexadecimal character is codified by 4 bits. Therefore, having 4 hex characters means you have 16 bits to code a color.
RGB565 uses 5 bits for red, 6 bits for green and 5 bits for blue. Having n bits for a color means it'll have 2^n possible values. 2^5 = 32 and 2^6 = 64, this is where the different values for each color you got from the Internet come from.
To split the RGB565 value into each separate color you would need to extract the corresponding bits for each one of them, for example, like this:
int redMask = 0b1111100000000000;
int greenMask = 0b0000011111100000;
int blueMask = 0b0000000000011111;
String color = "0xFFE0";
int colorAsInteger = Integer.parseInt(color.substring(2,color.length()), 16); // convert the Hex value to int
int R = (colorAsInteger & redMask) >> 11; // keep only red bits
int G = (colorAsInteger & greenMask) >> 5; // keep only green bits
int B = colorAsInteger & blueMask; // keep only blue bits
System.out.println(R + " " + G + " " + B);
The typical hex representation of RGB colors is the same as RGB888, i'll try to show this with examples. Guess we've got the color
0xFF8800, which is literally
1111.1111.1000.1000.0000.0000 as a binary number, where its components are:
R = FF = 1111.1111 = 255(dots are only for helping the view)
G = 88 = 1000.1000 = 136
B = 00 = 0000.0000 = 0
So, the translation is immediate (well, there's no translation indeed), and each component can have a value from 00 to FF (0 to 255 in decimal base)
The case with RGB565 is different. You only have 5 bits (or 6 in case of green) to represent that component of the color.
You can see each component as the percentage of participation in the global color.
In the example of 0xFF8800:
Red component participates with a 100% (it has the maximum possible value for a component, 255)
Green participates with a 53.33% (it has the value 136 over 255)
Blue participates with a 0%, this one is obvious.
If you apply this percentages of color to the RGB565 color, you will got the values of each component.
So, to translate 0xFF8800 to RGB565, calculate each percentage
R = 1 * 31 = 31 //(percentage over 100 by the maximum value of red in RGB565 = 2^5, minus 1)
G = 0.5333 * 63 = 33.6 //(you should round this value to integer)
B = 0 * 31 = 0
With this, the final number is:
31 34 0
11111.100010.00000
or
1111.1100.0100.0000
in hex
0xFC40
Not sure if the explanation is the best, but hope it helps.
You cannot simply split the string like you were doing for the rgb888 format.
What you should do is converting the full string to a number and then split this number using bit shifting like this :
String color = "0xFFE0";
int rgb = Integer.valueOf(color.substring(2,6), 16);
int r = (rgb & 0b1111100000000000) >> 11;
int g = (rgb & 0b0000011111100000) >> 5;
int b = (rgb & 0b0000000000011111) >> 0;
I've got this loop that is run thousands of times (so needs to be efficient). It changes the value of the bitmap pixel.
I want to be able to run thought the loop and "switch" a certain group of pixels to alpha and then switch them back at a later point.
My question is.
How do I switch the values? So say 0xFFCC1BE0 becomes 0x00CC1BE0 and then if I want to switch back to 0xFFCC1BE0 I simply take the 00 and turn it too FF.
I can't make two bitmaps as I run out of memory :-(
Anyhow here's what I've got so far:
private void setTransparencyOnLightMap(float WidthPercentage, float LeftPosition)
{
int blankPixel = 0x00000000;
int savedPixel = 0x00000000;
int desiredAlpha = 200; //Can also be 0x00
//Find away of turning alhpa off and on.
for(int BMx = 0; BMx < mLightMap.getWidth(); BMx++)
{
for(int BMy = 0; BMy < mLightMap.getHeight(); BMy++)
{
if(mLightMap.getPixel(BMx, BMy) != blankPixel) //Make sure don't overwrite blank transparent pixels.
{
savedPixel = mLightMap.getPixel(BMx,BMy);
savedPixel = savedPixel | (desiredAlpha << 24);
mLightMap.setPixel(BMx, BMy, savedPixel);
}
}
}
}
You could switch the alpha of a pixel like so:
savedPixel = savedPixel & 0x00FFFFFF;
savedPixel = savedPixel | (desiredAlpha << 24);
The first line zeros out the 8 most significant bits of savedPixel (these are the bits where the alpha is held). The second line sets the 8 most significant bits of savedPixel to desiredAlpha. Note that desiredAlpha must be between 0 and 255 (These are the ints that can be stored in 8 bits).
Note that this uses bitwise operators, (&, |, <<) which are very efficient.
It seems to me, to reduce memory use, you can just save the original Alpha value of each pixel rather than the whole ARGB value - to do this use a byte array which will be 1/4 the size of the original bitmap. Also use a bit-mask for the new Alpha so you can use bitwise AND (&) as described by Tristan Hull...
byte[] savedAlphaArray = new byte[mLightMap.getWidth(), mLightMap.getHeight()];
int desiredAlphaMask = 0x00FFFFFF;
int pixel;
Then to save the Alpha values and apply the bit-mask do the following...
for (int i = 0; i < mLightMap.getWidth(); i++) {
for (int j = 0; j < mLightMap.getHeight(); j++) {
pixel = mLightMap.getPixel(i, j);
savedAlphaArray[i, j] = (pixel & 0xFF000000) >> 24;
mLightMap.setPixel(i, j, desiredAlphaMask & pixel);
}
}
To 'switch' back do the following...
for (int i = 0; i < mLightMap.getWidth(); i++) {
for (int j = 0; j < mLightMap.getHeight(); j++) {
pixel = mLightMap.getPixel(i, j);
mLightMap.setPixel(i, j, savedAlphaArray[i, j] << 24 & pixel);
}
}
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 ?