shift operator syntax error in android - android

Was just wondering if you could use the shift operator in android I am getting a syntax error when trying it. the operator is >> << >>> . If it doesn't support it is their an android sdk equivalent?
EDIT: here is the code i am using. I am trying to do a per pixel collision detection and was trying this out.
public void getBitmapData(Bitmap bitmap1, Bitmap bitmap2){
int[] bitmap1Pixels;
int[] bitmap2Pixels;
int bitmap1Height = bitmap1.getHeight();
int bitmap1Width = bitmap1.getWidth();
int bitmap2Height = bitmap1.getHeight();
int bitmap2Width = bitmap1.getWidth();
bitmap1Pixels = new int[bitmap1Height * bitmap1Width];
bitmap2Pixels = new int[bitmap2Height * bitmap2Width];
bitmap1.getPixels(bitmap1Pixels, 0, bitmap1Width, 1, 1, bitmap1Width - 1, bitmap1Height - 1);
bitmap2.getPixels(bitmap2Pixels, 0, bitmap2Width, 1, 1, bitmap2Width - 1, bitmap2Height - 1);
// Find the first line where the two sprites might overlap
int linePlayer, lineEnemy;
if (ninja.getY() <= enemy.getY()) {
linePlayer = enemy.getY() - ninja.getY();
lineEnemy = 0;
} else {
linePlayer = 0;
lineEnemy = ninja.getY() - enemy.getY();
}
int line = Math.max(linePlayer, lineEnemy);
// Get the shift between the two
int x = ninja.getX() - enemy.getX();
int maxLines = Math.max(bitmap1Height, bitmap2Height);
for (; line <= maxLines; line ++) {
// if width > 32, then you need a second loop here
long playerMask = bitmap1Pixels[linePlayer];
long enemyMask = bitmap2Pixels[lineEnemy];
// Reproduce the shift between the two sprites
if (x < 0) playerMask << (-x);
else enemyMask << x;
// If the two masks have common bits, binary AND will return != 0
if ((playerMask & enemyMask) != 0) {
// Contact!
Log.d("pixel collsion","we have pixel on pixel");
}
}
}

If you're appending to a string you'll get an error unless you put the arithmetic operations in parentheses:
jcomeau#intrepid:/tmp$ cat test.java
public class test {
public static void main(String args[]) {
int test = 42;
System.out.println("" + (test >> 1) + ", " + (test << 1) + ", " + (test >>> 1));
}
}
jcomeau#intrepid:/tmp$ java test
21, 84, 21

Java, which is used by Android does support bitwise operations. Here's a handy guide.

Related

Find scale between three colors

I am not a Android developer, but my team members required the same thing I did on the web. I required a function to which I pass any three colors (e.g. red,blue,green), and I will pass a count, e.g. 100.
Definition of function
function getColorArray(mincolor,midcolor,maxcolor,100){
return colorarray;
}
When I have to call function:
getColorArray(red,yellow,green,100)
So it will give a array of 100 colors from a red,blue,green color scale.
I did it in Javascript. Here is the fiddle link.
I want the same output in Android.
This code does a simple line interpolation (c1 - c2, c2 - c3) . Your example JS code has richer options than this simple example (non linear interpolations), but I think this should help you get started.
You should probably define some custom colors if you're going to let the users name the colors - the default range of system colors is pretty limited (at least with java.awt.Color predifined colors, that is).
import java.awt.*;
import javax.swing.*;
import java.lang.reflect.Field;
public class ColorTest {
public static void main(String[] args) {
int n = args.length > 0 ? Integer.parseInt(args[0]) : 5;
Color[] test = getColorArray("red", "green", "blue", n);
for(Color c : test) {
System.out.println(c);
}
}
public static Color[] getColorArray(String c1, String c2, String c3, int n) {
Color[] inputColors = new Color[3];
try {
Field field1 = Color.class.getField(c1);
Field field2 = Color.class.getField(c2);
Field field3 = Color.class.getField(c3);
inputColors[0] = (Color) field1.get(null);
inputColors[1] = (Color) field2.get(null);
inputColors[2] = (Color) field3.get(null);
} catch (Exception e) {
System.err.println("One of the color values is not defined!");
System.err.println(e.getMessage());
return null;
}
Color[] result = new Color[n];
int[] c1RGB = { inputColors[0].getRed(), inputColors[0].getGreen(), inputColors[0].getBlue() };
int[] c2RGB = { inputColors[1].getRed(), inputColors[1].getGreen(), inputColors[1].getBlue() };
int[] c3RGB = { inputColors[2].getRed(), inputColors[2].getGreen(), inputColors[2].getBlue() };
int[] tmpRGB = new int[3];
tmpRGB[0] = c2RGB[0] - c1RGB[0];
tmpRGB[1] = c2RGB[1] - c1RGB[1];
tmpRGB[2] = c2RGB[2] - c1RGB[2];
float mod = n/2.0f;
for (int i = 0; i < n/2; i++) {
result[i] = new Color(
(int) (c1RGB[0] + i/mod*tmpRGB[0]) % 256,
(int) (c1RGB[1] + i/mod*tmpRGB[1]) % 256,
(int) (c1RGB[2] + i/mod*tmpRGB[2]) % 256
);
}
tmpRGB[0] = c3RGB[0] - c2RGB[0];
tmpRGB[1] = c3RGB[1] - c2RGB[1];
tmpRGB[2] = c3RGB[2] - c2RGB[2];
for (int i = 0; i < n/2 + n%2; i++) {
result[i+n/2] = new Color(
(int) (c2RGB[0] + i/mod*tmpRGB[0]) % 256,
(int) (c2RGB[1] + i/mod*tmpRGB[1]) % 256,
(int) (c2RGB[2] + i/mod*tmpRGB[2]) % 256
);
}
return result;
}
}

Converting I420 to BGRA

I wang to converting I420 to BGRA ,but i only search the method converting I420 to ARGB:
public static int[] I420toARGB(byte[] yuv, int width, int height)
{
boolean invertHeight=false;
if (height<0)
{
height=-height;
invertHeight=true;
}
boolean invertWidth=false;
if (width<0)
{
width=-width;
invertWidth=true;
}
int iterations=width*height;
int[] rgb = new int[iterations];
for (int i = 0; i<iterations;i++)
{
int nearest = (i/width)/2 * (width/2) + (i%width)/2;
int y = yuv[i] & 0x000000ff;
int u = yuv[iterations+nearest] & 0x000000ff;
int v = yuv[iterations + iterations/4 + nearest] & 0x000000ff;
int b = (int)(y+1.8556*(u-128));
int g = (int)(y - (0.4681*(v-128) + 0.1872*(u-128)));
int r = (int)(y+1.5748*(v-128));
if (b>255){b=255;}
else if (b<0 ){b = 0;}
if (g>255){g=255;}
else if (g<0 ){g = 0;}
if (r>255){r=255;}
else if (r<0 ){r = 0;}
int targetPosition=i;
if (invertHeight)
{
targetPosition=((height-1)-targetPosition/width)*width + (targetPosition%width);
}
if (invertWidth)
{
targetPosition=(targetPosition/width)*width + (width-1)-(targetPosition%width);
}
rgb[targetPosition] = (0xff000000) | (0x00ff0000 & r << 16) | (0x0000ff00 & g << 8) | (0x000000ff & b);
}
return rgb;
}
so ,if i only modify the last row:
rgb[targetPosition] = (0x000000ff & b) | (0x0000ff00 & g << 8)| (0x00ff0000 & r << 16) | (0xff000000);
No, changing the order of r…g…b…a in the last line is not enough. Also, the original code is wrong, because logical and & takes precedence before shift <<.
bgra[targetPosition] = 255 | (r << 8) | (g << 16) | (b < 24);
But this conversion is painfully slow; I would recommend to use libyuv that uses highly optimized native code. Out of the box, it comes with
int J420ToARGB(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_argb,
int dst_stride_argb,
int width,
int height);
To convert a single semi-planar byte array, you will need your own wrapper, based on Android420ToARGB().

Understanding Android RingDroid WAV Calculations

I have been studying the RingDroid source, trying to figure out how to draw waveforms on Android device. However, I got stuck in the section about reading the WAV file at CheapWAV.java.
public void ReadFile(File inputFile)
throws java.io.FileNotFoundException,
java.io.IOException {
super.ReadFile(inputFile);
mFileSize = (int)mInputFile.length();
if (mFileSize < 128) {
throw new java.io.IOException("File too small to parse");
}
FileInputStream stream = new FileInputStream(mInputFile);
byte[] header = new byte[12];
stream.read(header, 0, 12);
mOffset += 12;
if (header[0] != 'R' ||
header[1] != 'I' ||
header[2] != 'F' ||
header[3] != 'F' ||
header[8] != 'W' ||
header[9] != 'A' ||
header[10] != 'V' ||
header[11] != 'E') {
throw new java.io.IOException("Not a WAV file");
}
mChannels = 0;
mSampleRate = 0;
while (mOffset + 8 <= mFileSize) {
byte[] chunkHeader = new byte[8];
stream.read(chunkHeader, 0, 8);
mOffset += 8;
int chunkLen =
((0xff & chunkHeader[7]) << 24) |
((0xff & chunkHeader[6]) << 16) |
((0xff & chunkHeader[5]) << 8) |
((0xff & chunkHeader[4]));
if (chunkHeader[0] == 'f' &&
chunkHeader[1] == 'm' &&
chunkHeader[2] == 't' &&
chunkHeader[3] == ' ') {
if (chunkLen < 16 || chunkLen > 1024) {
throw new java.io.IOException(
"WAV file has bad fmt chunk");
}
byte[] fmt = new byte[chunkLen];
stream.read(fmt, 0, chunkLen);
mOffset += chunkLen;
int format =
((0xff & fmt[1]) << 8) |
((0xff & fmt[0]));
mChannels =
((0xff & fmt[3]) << 8) |
((0xff & fmt[2]));
mSampleRate =
((0xff & fmt[7]) << 24) |
((0xff & fmt[6]) << 16) |
((0xff & fmt[5]) << 8) |
((0xff & fmt[4]));
if (format != 1) {
throw new java.io.IOException(
"Unsupported WAV file encoding");
}
} else if (chunkHeader[0] == 'd' &&
chunkHeader[1] == 'a' &&
chunkHeader[2] == 't' &&
chunkHeader[3] == 'a') {
if (mChannels == 0 || mSampleRate == 0) {
throw new java.io.IOException(
"Bad WAV file: data chunk before fmt chunk");
}
int frameSamples = (mSampleRate * mChannels) / 50;
mFrameBytes = frameSamples * 2;
mNumFrames = (chunkLen + (mFrameBytes - 1)) / mFrameBytes;
mFrameOffsets = new int[mNumFrames];
mFrameLens = new int[mNumFrames];
mFrameGains = new int[mNumFrames];
byte[] oneFrame = new byte[mFrameBytes];
int i = 0;
int frameIndex = 0;
while (i < chunkLen) {
int oneFrameBytes = mFrameBytes;
if (i + oneFrameBytes > chunkLen) {
i = chunkLen - oneFrameBytes;
}
stream.read(oneFrame, 0, oneFrameBytes);
int maxGain = 0;
for (int j = 1; j < oneFrameBytes; j += 4 * mChannels) {
int val = java.lang.Math.abs(oneFrame[j]);
if (val > maxGain) {
maxGain = val;
}
}
mFrameOffsets[frameIndex] = mOffset;
mFrameLens[frameIndex] = oneFrameBytes;
mFrameGains[frameIndex] = maxGain;
frameIndex++;
mOffset += oneFrameBytes;
i += oneFrameBytes;
if (mProgressListener != null) {
boolean keepGoing = mProgressListener.reportProgress(
i * 1.0 / chunkLen);
if (!keepGoing) {
break;
}
}
}
} else {
stream.skip(chunkLen);
mOffset += chunkLen;
}
}
}
Everything seems straight forward until I reach
int frameSamples = (mSampleRate * mChannels) / 50;
mFrameBytes = frameSamples * 2;
mNumFrames = (chunkLen + (mFrameBytes - 1)) / mFrameBytes;
Q1. Where did the 50 magic number came from? Is it just assuming the frame duration is 50?
Q2. Why is mFrameBytes = frameSample * 2? Is it assuming each sample is 2 byte? But why?
for (int j = 1; j < oneFrameBytes; j += 4 * mChannels) {
int val = java.lang.Math.abs(oneFrame[j]);
if (val > maxGain) {
maxGain = val;
}
}
Q3. Why is j incrementing by 4 * mChannels? How was 4 justified?
Q4. What does frameGains mean actually? I've went through although articles/blogs such as
https://ccrma.stanford.edu/courses/422/projects/WaveFormat/2
http://blogs.msdn.com/b/dawate/archive/2009/06/23/intro-to-audio-programming-part-2-demystifying-the-wav-format.aspx
http://www.speakingcode.com/2011/12/31/primer-on-digital-audio-and-pulse-code-modulation-pcm/
But I don't see such term mentioned any where.
Hope someone can shed some light on this. Thank you.
Q1. Where did the 50 magic number came from? Is it just assuming the frame duration is 50?
A1. That calculates 1/50th of a second as a frame. So the app would have to process 50 frame buffers if audio data per second.
Q2. Why is mFrameBytes = frameSample * 2? Is it assuming each sample is 2 byte? But why?
A2. I'm guessing this because he is assuming 16bit samples.
Q3. Why is j incrementing by 4 * mChannels? How was 4 justified?
A3. I think the key here is to note it starts from offset 1. Which means he is only sampling the high order byte for the sample. The 4 is probably just an optimisation so he's only processing a half the buffer (remember he's assuming 2 bytes per sample)
Q4. What does frameGains mean actually?
Well it's exactly what it says. It's the gain of that frame (1/50th of a second) See http://en.m.wikipedia.org/wiki/Gain or Google for: Audio Gain.
This should also help: https://ccrma.stanford.edu/courses/422/projects/WaveFormat/

Compare RGB color values of two images in android

To get RGB values of one image i used the follwing code snippet
int[] pix = new int[picw * pich];
bitmap.getPixels(pix, 0, picw, 0, 0, picw, pich);
int R, G, B,Y;
for (int y = 0; y < pich; y++){
for (int x = 0; x < picw; x++)
{
int index = y * picw + x;
int R = (pix[index] >> 16) & 0xff; //bitwise shifting
int G = (pix[index] >> 8) & 0xff;
int B = pix[index] & 0xff;
//R,G.B - Red, Green, Blue
//to restore the values after RGB modification, use
//next statement
pix[index] = 0xff000000 | (R << 16) | (G << 8) | B;
}}
I want to compare two images,i know that comparing pixel values would be more expensive.I also analysed OpenCV library but i won't
get into my requirement.
Is there any algorithm to compare images using RGB values in android?
or
Is any other method to compare RGB values?
Thanks,
I'm not sure what your requirements are, but if all you want to do is compare the (RGB) color palettes of two images, you might want to use the PaletteFactory methods from Apache Commons Imaging (fka "Sanselan"):
The PaletteFactory methods build up collections (int[] and List<>) which can then be iterated over. I'm not sure just what kind of comparison you need to do, but a fairly simple case, using e.g. makeExactRgbPaletteSimple(), would be:
final File img1 = new File("path/to/image_1.ext")
final File img2 = new File("path/to/image_2.ext")
final PaletteFactory pf;
final int MAX_COLORS = 256;
final Palette p1 = pf.makeExactRgbPaletteSimple(img1, MAX_COLORS);
final Palette p2 = pf.makeExactRgbPaletteSimple(img2, MAX_COLORS);
final ArrayList<Int> matches = new ArrayList<Int>(Math.max(p1.length(), p2.length()));
int matchPercent;
// Palette objects are pre-sorted, afaik
if ( (p1 != null) && (p2 != null) ) {
if (p1.length() > p2.length()) {
for (int i = 0; i < p1.length(); i++) {
final int c1 = p1.getEntry(i);
final int c2 = p2.getPaletteIndex(c1);
if (c2 != -1) {
matches.add(c1);
}
}
matchPercent = ( (int)( (float)matches.size()) / ((float)p1.length) * 100 ) )
} else if (p2.length() >= p1.length()) {
for (int i = 0; i < p1.length(); i++) {
final int c1 = p2.getEntry(i);
final int c2 = p1.getPaletteIndex(c1);
if (c2 != -1) {
matches.add(c1);
}
}
matchPercent = ( (int)( (float)matches.size()) / ((float)p2.length) * 100 ) )
}
}
This is just a minimal example which may or may not compile and is almost certainly not what you're looking for in terms of comparison logic.
Basically what it does is check if each member of p1 is also a member of p2, and if so, adds it to matches. Hopefully the logic is correct, no guarantees. matchPercent is the percentage of colors which exist in both Palettes.
This is probably not the comparison method you want. It is just a simple example.
You will definitely need to play around with the 2nd parameter to makeExactRgbPaletteSimple(), int max, as I chose 256 arbitrarily - remember, the method will (annoyingly, imo) return null if max is too small.
I would suggest building from source as the repos have not been updated for quite some time. The project is definitely not mature, but it is fairly small, reasonably fast for medium-sized images, and pure Java.
Hope this helps.

How to get programmatically a list of colors from a gradient on Android

in Android I would like to draw a PieChart with a dynamically number of pies. Each pie should have a different color from a gradient.
For example I would like to have a gradient from light brown to dark brown. If I need to draw five pies, I need five volors from the start to the end of this gradient.
How can I do that in Java with the Android framework?
I found out that I can create a LinearGradient for a line, i.e.:
LinearGradient lg = new LinearGradient(1, 1, 5, 5, toRGB("lightbrown"), toRGB("darkbrown"), TileMode.REPEAT);
But I did not found any function to get a color from this line, i.e.:
// for the five needed RGB colors from the gradient line
lg.getRGBColor(1, 1);
lg.getRGBColor(2, 2);
lg.getRGBColor(3, 3);
lg.getRGBColor(4, 4);
lg.getRGBColor(5, 5);
Do you have any ideas how I can get this?
Thanks!
You cannot get these values directly from the LinearGradient. The gradient doesn't contain the actual drawing. To get these values, you can paint them to a canvas and pull the colors out of the canvas, or what I'd suggest would be to calculate the values yourself.
It's a repeating linear gradient in five steps and you have the RGB values for the first and last color. The rest is just math. Here's the pseudo code:
int r1 = startColor.red;
int g1 = startColor.green;
int b1 = startColor.blue;
int r2 = endColor.red;
int g2 = endColor.green;
int b2 = endColor.blue;
int redStep = r2 - r1 / 4;
int greenStep = g2 - g1 / 4;
int blueStep = b2 - b1 / 4;
firstColor = new Color(r1, g1, b1);
secondColor = new Color(r1 + redStep, g1 + greenStep, b1 + blueStep);
thirdColor = new Color(r1 + redStep * 2, g1 + greenStep * 2, b1 + blueStep * 2);
fourthColor = new Color(r1 + redStep * 3, g1 + greenStep * 3, b1 + blueStep * 3);
fifthColor = new Color(r1 + redStep * 4, g1 + greenStep * 4, b1 + blueStep * 4);
Another approach that is a little more reusable (I seem to bump into this problem all the time). It's a bit more code. Here is the usage:
int[] colors = {toRGB("lightbrown"), toRGB("darkbrown")};//assuming toRGB : String -> Int
float[] positions = {1, 5};
getColorFromGradient( colors, positions, 1 )
//...
getColorFromGradient( colors, positions, 5 )
Supporting functions
public static int getColorFromGradient(int[] colors, float[] positions, float v ){
if( colors.length == 0 || colors.length != positions.length ){
throw new IllegalArgumentException();
}
if( colors.length == 1 ){
return colors[0];
}
if( v <= positions[0]) {
return colors[0];
}
if( v >= positions[positions.length-1]) {
return colors[positions.length-1];
}
for( int i = 1; i < positions.length; ++i ){
if( v <= positions[i] ){
float t = (v - positions[i-1]) / (positions[i] - positions[i-1]);
return lerpColor(colors[i-1], colors[i], t);
}
}
//should never make it here
throw new RuntimeException();
}
public static int lerpColor( int colorA, int colorB, float t){
int alpha = (int)Math.floor(Color.alpha(colorA) * ( 1 - t ) + Color.alpha(colorB) * t);
int red = (int)Math.floor(Color.red(colorA) * ( 1 - t ) + Color.red(colorB) * t);
int green = (int)Math.floor(Color.green(colorA) * ( 1 - t ) + Color.green(colorB) * t);
int blue = (int)Math.floor(Color.blue(colorA) * ( 1 - t ) + Color.blue(colorB) * t);
return Color.argb(alpha, red, green, blue);
}
I have wrote the util class for calculate colors gradient.
via very, very simple Kotlin code:
val pink = Colar(245, 9, 253)
val lime = Colar(0, 253, 32)
lp_1.colors = (pink toColor lime).run {
gradient { 0 upTo 3 }
}
lp_2.colors = (pink toColor lime).run {
gradient { 0 upTo 9 }
}
lp_3.colors = (pink toColor lime).run {
gradient { 3 upTo 9}
}
Supporting util class
class StepGradientUtil(private var colar1: Colar?, private var colar2: Colar?) {
private var mSteps: Int = 0
infix fun StepGradientUtil.gradient(f: () -> IntRange): IntArray {
val result = f.invoke().map {
it.colorStep()
}.toIntArray()
recycler()
return result
}
infix fun Int.upTo(steps: Int): IntRange {
mSteps = steps
return (this until steps)
}
private fun recycler() {
mSteps = 0
colar1 = null
colar2 = null
}
private fun Int.colorStep() = Color.rgb(
(colar1!!.r * (mSteps - this) + colar2!!.r * this) / mSteps,
(colar1!!.g * (mSteps - this) + colar2!!.g * this) / mSteps,
(colar1!!.b * (mSteps - this) + colar2!!.b * this) / mSteps
)
}
data class Colar(
val r: Int,
val g: Int,
val b: Int
)
infix fun Colar.toColor(colar: Colar) = StepGradientUtil(colar1 = this, colar2 = colar)
See full source code sample on repo

Categories

Resources