so i am trying to convert an image into a string/hexadecimal array (containing pixel color values) and send it over bluetooth to my arduino controller. I have converted the image to hex array but am unable to send it over bluetooth.
Following is the image to hex-conversion block:
public void getPixelValue (View v){
Bitmap bm = ((BitmapDrawable) imgView.getDrawable()).getBitmap();
boolean hasDrawable = (bm != null);
if(hasDrawable)
{
picw = bm.getWidth();
pich = bm.getHeight();
int[] pix = new int[picw * pich];
bm.getPixels(pix, 0, picw, 0, 0, picw, pich);
int R, G, B,Y;
colorArray = new String[picw][pich];
for (int i = 0; i < picw; i++)
{
for (int j = 0; j < pich; j++)
{
int pixel = bm.getPixel(i,j);
R = Color.red(pixel);
G = Color.green(pixel);
B = Color.blue(pixel);
StringBuilder builder = new StringBuilder();
builder.append("0x");
builder.append(Integer.toHexString(R));
builder.append(Integer.toHexString(G));
builder.append(Integer.toHexString(B));
colorArray[i][j] = builder.toString();
}
}
}
else
{
Toast.makeText(this, "No Image loaded", Toast.LENGTH_SHORT).show();
}
}
Kindly guide on how to send it over bluetooth so that i receive the array as it is on the arduino (nano) side.
This here is the method i am using to send simple text/characters. I type the string, in a textbox, i want to read on the serial monitor (arduino side).
public void sendText (View v) {
try
{
String msg = txtBox.getText().toString();
msg += "\n";
mmOutputStream.write(msg.getBytes());
Toast.makeText(this, "Data Sent", Toast.LENGTH_LONG).show();
}
catch (IOException ex) { }
}
This block works perfectly so i know that the bluetooth pairing and connection is OK. Next, i want to send the string/hex array i have obtained from the 'getpixelvalue' function.
Related
I am implementing POS bluetooth printer with ESC/POS commands and trying to print bitmap image.
Image is getting printing but always it is printing some white space at start and then printing an image,because of which i am not able to print 1 image per label.
following is my code for printing and image
int bmpNewWidth = bmp.getWidth();
int bmpNewHeight = bmp.getHeight();
byte[] printBMPPackageHead = ESCUtil.bmpCmdHead(bmpMode,bmpNewWidth);
int bmpBlockHeight = 0;
int bmpBlockNums =0;
if((bmpMode == 0) || (bmpMode ==1))
{
bmpBlockHeight = 8;
}
else if((bmpMode == 32) || (bmpMode ==33))
{
bmpBlockHeight = 24;
}
else
{
Log.d(TAG,"****bmpMode set error!!*****");
return (new byte[1]);
}
bmpBlockNums = ((bmpNewHeight % bmpBlockHeight) == 0)? (bmpNewHeight/bmpBlockHeight) : (bmpNewHeight/bmpBlockHeight +1);
int bmpBlockCMDSize = printBMPPackageHead.length + bmpNewWidth*bmpBlockHeight/8;
byte[] bmpPrintData = new byte[bmpBlockNums*bmpBlockCMDSize];
for(int n = 0; n < bmpBlockNums; n++)
{
byte[] bmpBlockPxBytes = getBitmapBlockData(n,bmpNewWidth,bmpBlockHeight,bmp);
byte[][] bmpBlockPrintData = {printBMPPackageHead,bmpBlockPxBytes};
System.arraycopy(ESCUtil.byteMerger(bmpBlockPrintData),0,bmpPrintData,n*bmpBlockCMDSize,bmpBlockCMDSize);
}
return bmpPrintData;
}
and
public static byte[] bmpCmdHead(int mode, int bitmapWidth)
{
//byte[] result = new byte[]{ESC,42,0,0,0};
byte[] result = new byte[]{ESC,42,0,0,0};
result[2] = (byte)mode;
result[3] = (byte)(bitmapWidth%256);
result[4] = (byte)(bitmapWidth/256);
return result;
}
public static byte[] getBitmapBlockData(int blocknum, int bmpWidth, int bmpBlockHeight, Bitmap bmp)
{
int blockHeightBytes = bmpBlockHeight/8;
byte[] blockData = new byte[bmpWidth*blockHeightBytes];
for (int i = 0;i < bmpWidth; i++)
{
for(int j = 0;j < blockHeightBytes;j++)
{
for(int p = 0; p < 8; p++)
{
byte px = px2Byte(i,blocknum * bmpBlockHeight+j*8+p,bmp);
blockData[i*blockHeightBytes+j] |= (px << (7-p));
}
}
}
return blockData;
}
this is it.Before calling this function i have called only init printer command that's it.
Please help me. Thanks in advance.
I am trying to make an android app for monument recognition. The input changes on every run but output returned is always same.
Below are the code snippets
to load tflite model stored in assets directory
private ByteBuffer loadModelFile(String filename) throws IOException {
AssetFileDescriptor fileDescriptor = this.getAssets().openFd(filename);
FileInputStream inputStream = new FileInputStream(fileDescriptor.getFileDescriptor());
FileChannel fileChannel = inputStream.getChannel();
long startOffset = fileDescriptor.getStartOffset();
long declaredLength = fileDescriptor.getDeclaredLength();
return fileChannel.map(FileChannel.MapMode.READ_ONLY, startOffset, declaredLength);
}
to initialize tflite interpreter
predict.setOnClickListener(new View.OnClickListener() {
#RequiresApi(api = Build.VERSION_CODES.O)
#Override
public void onClick(View v) {
try {
tflite = new Interpreter(loadModelFile("converted_model.tflite"));
Log.println(7,"tflite", "tflite init");
doInference(picFile);
} catch (Exception e) {
System.out.println(e);
}
}
});
to run the model
#RequiresApi(api = Build.VERSION_CODES.O)
public void doInference(File photo) throws IOException {
img = findViewById(R.id.imgToDisp);
Bitmap bitmapImg = BitmapFactory.decodeFile(pathToFile);
img.setImageBitmap(bitmapImg);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmapImg.compress(Bitmap.CompressFormat.JPEG, 50, stream);
byte[] arr = stream.toByteArray();
changedim = new float[1][150][150][3];
outputval = new float[1][28];
int m = 0;
for (int i = 0; i < 1; i++) {
for (int j = 0; j < 150; j++) {
for (int k = 0; k < 150; k++) {
for (int l = 0; l < 3; l++) {
byte a = arr[m++];
changedim[i][j][k][l] = Byte.toUnsignedLong(a);
}
}
}
}
tflite.run(changedim, outputval);
for(int i=0;i<28;i++) {
Log.println(7,"outputval",i+" "+outputval[0][i]);
}
path = findViewById(R.id.path);
String out = "";
float[] op = outputval[0];
int ind = 0;
float max = op[0];
while (op[ind] != 1) {
ind++;
//Log.println(7,"op", " "+op[ind]+" "+ind);
}
for (float f : op) {
out += Float.toString(f) + ",";
}
predict.setText("result: " + labels.get(ind));
Log.println(7, "label", ind + " " + labels.get(ind));
//path.setText(""+pathToFile);
}
input to the model must be an image of size 150*150 converted to 4d float32 array of shape 1*150*150*3
Input to the model is the color values of individual pixels.
Which can be extracted using
int p = bitmapImg.getPixel(j, k);
int R = (p >> 16) & 0xff;
int G = (p >> 8) & 0xff;
int B = p & 0xff;
change that and your model will work correctly!
I am developing in Android BLE.
I try to send string to BLE device(like TI CC2541) , and it seems can not send string direct to BLE device.
It need to convert the String to Byte.
I have search some information , there has someone use URLEncoder.encode.
But I am not sure which is the answer what I need.
But how to convert the String to Byte?
The following code is writeCharacteristic for BLE
public void writeString(String text) {
// TODO Auto-generated method stub
BluetoothGattService HelloService = mBluetoothGatt.getService(HELLO_SERVICE_UUID);
BluetoothGattCharacteristic StringCharacteristic = HelloService.getCharacteristic(UUID_HELLO_CHARACTERISTIC_WRITE_STRING);
mBluetoothGatt.setCharacteristicNotification(StringCharacteristic , true);
int A = Integer.parseInt(text);
//How to convert the String to Byte here and set the Byte to setValue ?????
StringCharacteristic .setValue(A, BluetoothGattCharacteristic.FORMAT_UINT8, 0);
mBluetoothGatt.writeCharacteristic(StringCharacteristic );
Log.d(TAG, "StepCount Characteristic End!");
}
How to convert the String to Byte?
Where you get your String:
byte[] strBytes = text.getBytes();
byte[] bytes = context.yourmWriteCharacteristic.getValue();
Please add a null check too like:
if (bytes == null) {
Log.w("Cannot get Values from mWriteCharacteristic.");
dismiss();// equivalent action
}
if (bytes.length <= strBytes.length) {
for(int i = 0; i < bytes.length; i++) {
bytes[i] = strBytes[i];
}
} else {
for (int i = 0; i < strBytes.length; i++) {
bytes[i] = strBytes[i];
}
}
Now, something like:
StepCount_Characteristic.setValue(bytes);
mBluetoothGatt.writeCharacteristic(StepCount_Characteristic);
I found the following code help me convert the string.
private byte[] parseHex(String hexString) {
hexString = hexString.replaceAll("\\s", "").toUpperCase();
String filtered = new String();
for(int i = 0; i != hexString.length(); ++i) {
if (hexVal(hexString.charAt(i)) != -1)
filtered += hexString.charAt(i);
}
if (filtered.length() % 2 != 0) {
char last = filtered.charAt(filtered.length() - 1);
filtered = filtered.substring(0, filtered.length() - 1) + '0' + last;
}
return hexStringToByteArray(filtered);
}
public static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i+1), 16));
}
return data;
}
private int hexVal(char ch) {
return Character.digit(ch, 16);
}
If you want to convert string value. you just need to call like the following:
String text;
byte[] value = parseHex(text);
Code to generate Qr code using zxing is ---
It takes string data and the imageview This works just fine
private void generateQRCode_general(String data, ImageView img)throws WriterException {
com.google.zxing.Writer writer = new QRCodeWriter();
String finaldata = Uri.encode(data, "utf-8");
BitMatrix bm = writer.encode(finaldata, BarcodeFormat.QR_CODE,150, 150);
Bitmap ImageBitmap = Bitmap.createBitmap(150, 150,Config.ARGB_8888);
for (int i = 0; i < 150; i++) {//width
for (int j = 0; j < 150; j++) {//height
ImageBitmap.setPixel(i, j, bm.get(i, j) ? Color.BLACK: Color.WHITE);
}
}
if (ImageBitmap != null) {
qrcode.setImageBitmap(ImageBitmap);
} else {
Toast.makeText(getApplicationContext(), getResources().getString(R.string.userInputError),
Toast.LENGTH_SHORT).show();
}
}
Now my question is ,how to get bar code using the same library.i saw some files related to bar codes but i am not sure how to do it.
Since I want to generate the bar code within the application and not call any web service. Since i am already using zxing,no point in including itext and barbecue jars
Like Gaskoin told... MultiFormatWrite it worked :) here is the code.
com.google.zxing. MultiFormatWriter writer =new MultiFormatWriter();
String finaldata = Uri.encode(data, "utf-8");
BitMatrix bm = writer.encode(finaldata, BarcodeFormat.CODE_128,150, 150);
Bitmap ImageBitmap = Bitmap.createBitmap(180, 40,Config.ARGB_8888);
for (int i = 0; i < 180; i++) {//width
for (int j = 0; j < 40; j++) {//height
ImageBitmap.setPixel(i, j, bm.get(i, j) ? Color.BLACK: Color.WHITE);
}
}
if (ImageBitmap != null) {
qrcode.setImageBitmap(ImageBitmap);
} else {
Toast.makeText(getApplicationContext(), getResources().getString(R.string.userInputError),
Toast.LENGTH_SHORT).show();
}
I've tested the accepted answer to generate a Barcode but the output is blurry when used in a big ImageView. To get a high quality output, the width of the BitMatrix, the Bitmap and the final ImageView should be the same. But doing so using the accepted answer will make the Barcode generation really slow (2-3 seconds). This happens because
Bitmap.setPixel()
is a slow operation, and the accepted answer is doing intensive use of that operation (2 nested for loops).
To overcome this problem I've modified a little bit the Bitmap generation algorithm (only use it for Barcode generation) to make use of Bitmap.setPixels() which is much faster:
private Bitmap createBarcodeBitmap(String data, int width, int height) throws WriterException {
MultiFormatWriter writer = new MultiFormatWriter();
String finalData = Uri.encode(data);
// Use 1 as the height of the matrix as this is a 1D Barcode.
BitMatrix bm = writer.encode(finalData, BarcodeFormat.CODE_128, width, 1);
int bmWidth = bm.getWidth();
Bitmap imageBitmap = Bitmap.createBitmap(bmWidth, height, Config.ARGB_8888);
for (int i = 0; i < bmWidth; i++) {
// Paint columns of width 1
int[] column = new int[height];
Arrays.fill(column, bm.get(i, 0) ? Color.BLACK : Color.WHITE);
imageBitmap.setPixels(column, 0, 1, i, 0, 1, height);
}
return imageBitmap;
}
This approach is really fast even for really big outputs and generates a high quality bitmap.
You are using QRCodeWriter. If you want to write another type of code, use another Writer.
Check this MultiFormatWriter - it can write any type of bar or find specific writers here in subfolders (this is from zxing library)
There you go,
public static Bitmap createBarCode (String codeData, BarcodeFormat barcodeFormat, int codeHeight, int codeWidth) {
try {
Hashtable<EncodeHintType, ErrorCorrectionLevel> hintMap = new Hashtable<EncodeHintType, ErrorCorrectionLevel> ();
hintMap.put (EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);
Writer codeWriter;
if (barcodeFormat == BarcodeFormat.QR_CODE) {
codeWriter = new QRCodeWriter ();
} else if (barcodeFormat == BarcodeFormat.CODE_128) {
codeWriter = new Code128Writer ();
} else {
throw new RuntimeException ("Format Not supported.");
}
BitMatrix byteMatrix = codeWriter.encode (
codeData,
barcodeFormat,
codeWidth,
codeHeight,
hintMap
);
int width = byteMatrix.getWidth ();
int height = byteMatrix.getHeight ();
Bitmap imageBitmap = Bitmap.createBitmap (width, height, Config.ARGB_8888);
for (int i = 0; i < width; i ++) {
for (int j = 0; j < height; j ++) {
imageBitmap.setPixel (i, j, byteMatrix.get (i, j) ? Color.BLACK: Color.WHITE);
}
}
return imageBitmap;
} catch (WriterException e) {
e.printStackTrace ();
return null;
}
}
Of course you can support as many BarcodeFormats as you want, just change the constructor here :
Writer codeWriter;
if (barcodeFormat == BarcodeFormat.QR_CODE) {
codeWriter = new QRCodeWriter ();
} else if (barcodeFormat == BarcodeFormat.CODE_128) {
codeWriter = new Code128Writer ();
} else {
throw new RuntimeException ("Format Not supported.");
}
try this code
Context context = getActivity();
Intent intent = new Intent("com.google.zxing.client.android.ENCODE");
intent.putExtra("ENCODE_TYPE", Text);
intent.putExtra("ENCODE_DATA", "12345678901");
intent.putExtra("ENCODE_FORMAT", "UPC_A");
startActivity(intent);
hope this helps you.
My Arduino is listening for a character to be sent from my phone to print sensor data to send back via a Bluetooth module. This is working fine and the communication is fast and accurate. However, the problem occurs when I request data from two different sensors.
I will request data from sensor A and get my results fine. I then request data from sensor B, and I get what seems to be a leftover request to sensor A and get information from sensor A again. I can request data from sensor B twice in a row, and I will then receive data from sensor B accurately.
I have tried to flush the input stream, but that made my application crash. I also tried to use InputStream.wait() and then interrupt the wait with InputStream.notify() when requesting data from a different sensor. This also crashed the program.
This is my receive code. The character that is being passed in is the character that defines what sensor data to send back from the Arduino.
public String receive(Character c) {
try {
myOutputStream.write(c);
final Handler handler = new Handler();
final byte delimiter = 10; // ASCII code for a newline
stopWorker = false;
readBufferPosition = 0;
readBuffer = new byte[1024];
myThread = new Thread(new Runnable() {
public void run() {
while (!Thread.currentThread().isInterrupted()
&& !stopWorker) {
try {
int bytesAvailable = myInputStream.available();
if (bytesAvailable > 0) {
byte[] packetBytes = new byte[bytesAvailable];
myInputStream.read(packetBytes);
for (int i = 0; i < bytesAvailable; i++) {
byte b = packetBytes[i];
if (b == delimiter) {
byte[] encodedBytes = new byte[readBufferPosition];
System.arraycopy(readBuffer, 0,
encodedBytes, 0,
encodedBytes.length);
final String data = new String(
encodedBytes, "US-ASCII");
readBufferPosition = 0;
handler.post(new Runnable() {
public void run() {
status = data;
}
});
} else {
readBuffer[readBufferPosition++] = b;
}
}
}
}
catch (IOException ex) {
stopWorker = true;
}
}
}
});
myThread.start();
return (status);
}
catch (IOException e) {
// TODO Auto-generated catch block
status = "Failed";
e.printStackTrace();
}
return (status);
}
This is some of the Arduino code, and it is very simple.
if(bluetooth.available()) //If something was sent from phone
{
char toSend = (char)bluetooth.read(); //Reads the char sent
if (toSend == 'T')
{
//If the char is T, turn on the light.
float voltage = analogRead(14) * 5.04;
voltage /= 1024.0;
float temperatureC = (voltage - .5) * 100;
float temperatureF = (temperatureC * 9.0 / 5.0) + 32.0;
bluetooth.println(temperatureF);
}
How can I fix this problem?