Convert a given string to a byteArrays - android

I have an encryption key and i want to convert this given string into a byte array, in order to do file decryption process.
Exemple :
val string = "0123456789012345678901234567890123456789012345678901234567890123"
// what i want to have is something like this :
val result = byteArrayOf(0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x00,0x01,0x02,0x03)

voila :
private fun hexStringToByteArray(s: String): ByteArray? {
val len = s.length
val data = ByteArray(len / 2)
var i = 0
while (i < len) {
data[i / 2] = ((Character.digit(s[i], 16) shl 4) +
Character.digit(s[i + 1], 16)).toByte()
i += 2
}
return data
}
from here https://stackoverflow.com/a/18714790/5015227

Related

How can I insert a char after n number of characters in Kotlin?

I want to add a char after n number of elements
Thanks in advance
fun String.appendChar(afterIndex: Int, afterChar: Char): String {
val sb = StringBuilder(this);
sb.insert(afterIndex + 1, afterChar);
return sb.toString();
}
val helloWorld = "Helo world"
fun main() {
println(helloWorld.appendChar(2, 'l'))
}
Just replace step and specificChar value
var charsList = "abcdefghijklmnopqrstuvwxyz"
val step = 5
val specificChar = '*'
for ( i in 1 .. charsList.length){
print(charsList[i-1])
if(i % step == 0)
print(specificChar)
}

Kotlin - retrieve bit position from byte and convert it as int

I've a byte. What I want to do is access bit position to retrieve boolean (0 or 1). How can I do that in Kotlin?
fun getBit(b: Byte, bitNumber: Int): Boolean {
val shift: Int = 7 - bitNumber
val bitMask = (1 shl shift).toByte()
val masked = (b and bitMask)
return masked.toInt() != 0
}
This for some reason return incorrect value of false when it should return true
Your algorithm seems OK, I think you just made an off by one error (although you didn't say if you are counting from 0 or 1). If I change it to
val shift: Int = 8 - bitNumber
It seems to work fine for me:
fun getBit(b: Byte, bitNumber: Int): Boolean {
require(bitNumber in 1..8)
val shift: Int = 8 - bitNumber
val bitMask = (1 shl shift).toByte()
val masked = (b and bitMask)
return masked.toInt() != 0
}
fun main() {
println(getBit(0b10000000.toByte(), 1))
println(getBit(0b10000000.toByte(), 2))
println(getBit(0b01000000, 2))
}
Output:
true
false
true
Note: you can avoid the experimental Byte.and() by using Int.and() instead:
val bitMask = (0b1 shl shift)
val masked = (b.toInt() and bitMask)
return masked != 0

What to use in Kotlin/Java for effective float collections handling?

I'm working on an audio editing app, and I need to store the samples as floats in an efficient way - memory as well as performance-wise. Right now I'm using simply Kotlin's List, but I've heard about potential gains from using FloatArray type. I made a synthetic test to see the benefits and the results are a bit weird. Any advice on the techniques and collections I should use for large datasets of this nature could earn you a cookie, if I had one and knew your location.
So I have two alternative channel implementations (as in - channel in an audio file), to hold my data.
Here is my code for the channel based on FloatArray:
class ArrayChannel {
private var mData : FloatArray = FloatArray(0)
private var mLastWrittenIndex = 0
fun getSamples(startIndex : Int = 0, endIndex : Int = mLastWrittenIndex) : FloatArray
= mData.sliceArray(IntRange(0, endIndex - 1))
fun insertSamples(samples : FloatArray, startIndex : Int = mLastWrittenIndex) {
if (mData.size - mLastWrittenIndex < samples.size) {
val newData = FloatArray(mData.size + samples.size )
mData.copyInto(newData, 0, 0, startIndex)
samples.copyInto(newData, startIndex)
mData.copyInto(newData, startIndex + samples.size, startIndex)
mData = newData
} else {
mData.copyInto(mData, startIndex + samples.size, startIndex, mLastWrittenIndex)
samples.copyInto(mData, startIndex)
}
mLastWrittenIndex += samples.size
}
fun getSamplesSize(): Int = mLastWrittenIndex
}
And here is my code for the channel based on List:
class Channel {
private var mData = mutableListOf<Float>()
fun getSamples(startIndex : Int = 0, endIndex : Int = mData.size) : List<Float>
= mData.slice(IntRange(0, endIndex - 1))
fun insertSamples(samples : List<Float>, startIndex : Int = mData.size) {
mData.addAll(startIndex, samples)
}
fun getSamplesSize() : Int = mData.size
}
Here is the measuring code:
val initialValuesArray = FloatArray(1000000) {Random.nextFloat()}
val valuesToAddArray = FloatArray(1000000) {Random.nextFloat()}
val initialValuesList = MutableList(1000000) {Random.nextFloat()}
val valuesToAddList = MutableList(1000000) {Random.nextFloat()}
var startTime = System.currentTimeMillis()
val arrayChannel = ArrayChannel()
arrayChannel.insertSamples(initialValuesArray)
arrayChannel.insertSamples(valuesToAddArray, 0)
println("Array time: ${System.currentTimeMillis() - startTime}")
startTime = System.currentTimeMillis()
val listChannel = Channel()
listChannel.insertSamples(initialValuesList)
listChannel.insertSamples(valuesToAddList, 0)
println("List time: ${System.currentTimeMillis() - startTime}")
Now, the average results from a direct fun main() call in Android studio are as following:
Array time: 56
List time: 6
A change in the allocation of the array, instead of mData.size + samples.size to mData.size + samples.size * 2, makes these different, in a very weird way:
Array time: 17
List time: 48
When I run the same code inside of an Activity instead of some main Kotlin function, the results match more what I was expecting and are promising:
2020-08-17 21:15:33.325 D/ARRAY_TIME: 15
2020-08-17 21:15:33.481 D/LIST_TIME: 156
Why the code behaves this way and what do you think would be a good way of handling lots of numerical data in the Android environment?

Cannot copy from a TensorFlowLite tensor (Identity_1) with shape [1, 3087, 2] to a Java object with shape [1, 3087]

I'm trying to run a YoloV4 model on Android that's been converted to .tflite. My input shape seems to be fine [1, 224, 224, 4] but the app crashes on my output shape. I'm using code from a Udacity course on tflite.
I get the above error when I run the following code:
class TFLiteObjectDetectionAPIModel private constructor() : Classifier {
override val statString: String
get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates.
private var isModelQuantized: Boolean = false
// Config values.
private var inputSize: Int = 0
// Pre-allocated buffers.
private val labels = Vector<String>()
private var intValues: IntArray? = null
// outputLocations: array of shape [Batchsize, NUM_DETECTIONS,4]
// contains the location of detected boxes
private var outputLocations: Array<Array<FloatArray>>? = null
// outputClasses: array of shape [Batchsize, NUM_DETECTIONS]
// contains the classes of detected boxes
private var outputClasses: Array<FloatArray>? = null
// outputScores: array of shape [Batchsize, NUM_DETECTIONS]
// contains the scores of detected boxes
private var outputScores: Array<FloatArray>? = null
// numDetections: array of shape [Batchsize]
// contains the number of detected boxes
private var numDetections: FloatArray? = null
private var imgData: ByteBuffer? = null
private var tfLite: Interpreter? = null
override fun recognizeImage(bitmap: Bitmap): List<Classifier.Recognition> {
// Log this method so that it can be analyzed with systrace.
Trace.beginSection("recognizeImage")
Trace.beginSection("preprocessBitmap")
// Preprocess the image data from 0-255 int to normalized float based
// on the provided parameters.
bitmap.getPixels(intValues, 0, bitmap.width, 0, 0, bitmap.width, bitmap.height)
imgData!!.rewind()
for (i in 0 until inputSize) {
for (j in 0 until inputSize) {
val pixelValue = intValues!![i * inputSize + j]
if (isModelQuantized) {
// Quantized model
imgData!!.put((pixelValue shr 16 and 0xFF).toByte())
imgData!!.put((pixelValue shr 8 and 0xFF).toByte())
imgData!!.put((pixelValue and 0xFF).toByte())
} else { // Float model
imgData!!.putFloat(((pixelValue shr 16 and 0xFF) - IMAGE_MEAN) / IMAGE_STD)
imgData!!.putFloat(((pixelValue shr 8 and 0xFF) - IMAGE_MEAN) / IMAGE_STD)
imgData!!.putFloat(((pixelValue and 0xFF) - IMAGE_MEAN) / IMAGE_STD)
}
}
}
Trace.endSection() // preprocessBitmap
// Copy the input data into TensorFlow.
Trace.beginSection("feed")
outputLocations = Array(1) { Array(NUM_DETECTIONS) { FloatArray(4) } }
outputClasses = Array(1) { FloatArray(NUM_DETECTIONS) }
outputScores = Array(1) { FloatArray(NUM_DETECTIONS) }
numDetections = FloatArray(1)
val inputArray = arrayOf<Any>(imgData!!)
val outputMap = ArrayMap<Int, Any>()
outputMap[0] = outputLocations!!
outputMap[1] = outputClasses!!
outputMap[2] = outputScores!!
outputMap[3] = numDetections!!
Trace.endSection()
// Run the inference call.
Trace.beginSection("run")
tfLite!!.runForMultipleInputsOutputs(inputArray, outputMap)
Trace.endSection()
// Show the best detections.
// after scaling them back to the input size.
val recognitions = ArrayList<Classifier.Recognition>(NUM_DETECTIONS)
for (i in 0 until NUM_DETECTIONS) {
val detection = RectF(
outputLocations!![0][i][1] * inputSize,
outputLocations!![0][i][0] * inputSize,
outputLocations!![0][i][3] * inputSize,
outputLocations!![0][i][2] * inputSize)
// SSD Mobilenet V1 Model assumes class 0 is background class
// in label file and class labels start from 1 to number_of_classes+1,
// while outputClasses correspond to class index from 0 to number_of_classes
val labelOffset = 1
recognitions.add(
Classifier.Recognition(
"" + i,
labels[outputClasses!![0][i].toInt() + labelOffset],
outputScores!![0][i],
detection))
}
Trace.endSection() // "recognizeImage"
return recognitions
}
override fun enableStatLogging(debug: Boolean) {
//Not implemented
}
override fun close() {
//Not needed.
}
override fun setNumThreads(numThreads: Int) {
if (tfLite != null) tfLite!!.setNumThreads(numThreads)
}
override fun setUseNNAPI(isChecked: Boolean) {
if (tfLite != null) tfLite!!.setUseNNAPI(isChecked)
}
companion object {
// Only return this many results.
private const val NUM_DETECTIONS = 3087
// Float model
private const val IMAGE_MEAN = 128.0f
private const val IMAGE_STD = 128.0f
/** Memory-map the model file in Assets. */
#Throws(IOException::class)
private fun loadModelFile(assets: AssetManager, modelFilename: String): MappedByteBuffer {
val fileDescriptor = assets.openFd(modelFilename)
val inputStream = FileInputStream(fileDescriptor.fileDescriptor)
val fileChannel = inputStream.channel
val startOffset = fileDescriptor.startOffset
val declaredLength = fileDescriptor.declaredLength
return fileChannel.map(FileChannel.MapMode.READ_ONLY, startOffset, declaredLength)
}
/**
* Initializes a native TensorFlow session for classifying images.
*
* #param assetManager The asset manager to be used to load assets.
* #param modelFilename The filepath of the model GraphDef protocol buffer.
* #param labelFilename The filepath of label file for classes.
* #param inputSize The size of image input
* #param isQuantized Boolean representing model is quantized or not
*/
#Throws(IOException::class)
fun create(
assetManager: AssetManager,
modelFilename: String,
labelFilename: String,
inputSize: Int,
isQuantized: Boolean): Classifier {
val d = TFLiteObjectDetectionAPIModel()
val labelsInput: InputStream?
val actualFilename = labelFilename.split("file:///android_asset/".toRegex())
.dropLastWhile { it.isEmpty() }.toTypedArray()[1]
labelsInput = assetManager.open(actualFilename)
val br: BufferedReader?
br = BufferedReader(InputStreamReader(labelsInput!!))
while (br.readLine()?.let { d.labels.add(it) } != null);
br.close()
d.inputSize = inputSize
try {
val options = Interpreter.Options()
options.setNumThreads(4)
d.tfLite = Interpreter(loadModelFile(assetManager, modelFilename), options)
} catch (e: Exception) {
throw RuntimeException(e)
}
d.isModelQuantized = isQuantized
// Pre-allocate buffers.
val numBytesPerChannel: Int = if (isQuantized) {
1 // Quantized
} else {
4 // Floating point
}
d.imgData = ByteBuffer.allocateDirect(1 * d.inputSize * d.inputSize * 3 * numBytesPerChannel)
d.imgData!!.order(ByteOrder.nativeOrder())
d.intValues = IntArray(d.inputSize * d.inputSize)
d.outputLocations = Array(1) { Array(NUM_DETECTIONS) { FloatArray(2) } }
d.outputClasses = Array(1) { FloatArray(NUM_DETECTIONS) }
d.outputScores = Array(1) { FloatArray(NUM_DETECTIONS) }
d.numDetections = FloatArray(1)
return d
}
}
When I change the outputLocation to
outputLocations = Array(1) { Array(NUM_DETECTIONS) { FloatArray(2) } }
I get the following error Cannot copy from a TensorFlowLite tensor (Identity) with shape [1, 3087, 4] to a Java object with shape [1, 3087, 2]
What is Identity and Identity_1? I've looked at my model on Netron and can see both but I'm not sure how to understand the model.
Can anyone help? Is there anything else I can change or is my model just not suitable for mobile platforms?
Cannot copy from a TensorFlowLite tensor (Identity) with shape [1, 25200, 8] to a Java object with shape [1, 80, 80, 255].
I have encountered similar problems and haven't found a solution yet

HERE SDK Prem - how to get compressedRoute?

I am trying to get hotels to the length of the route, using REST request
The request has a parameter compressedRoute, but the conversion algorithm in Java script language.
Is there such an algorithm in Java or Kotlin? Maybe such a request is in the SDK, but I do not see it?
points to take from route.routeElements.geometry.allPoints?
I managed to compress the route. The problem was in the error of the example on JS.
First you need to go through to limit the number of points in the route, I set 120. If you do more, 414 errors may occur
fun execute(route: Route, categoryName: String, radiusInMeters: Int): Single<List<ItemPlaceByCorridor>> {
val allPointList = route.routeGeometry
val pointList = ArrayList<GeoCoordinate>()
for ((index, elem) in allPointList.withIndex()) {
if (index % (allPointList.size / POINTS_IN_ROUTE) == 0 || (index == 0) || (index == allPointList.lastIndex)) {
pointList.add(elem)
}
}
var routeStr = hereEncodePolyline(pointList)
routeStr += ";w=$radiusInMeters"
return mHereMapsApi.getPlacesByCorridor(categoryName, routeStr)
.map { response -> response.results.listItems }
}
Algorithm transferred from JS to Kotlin
private fun hereEncodePolyline(positions: List<GeoCoordinate>): String {
var lastLat = 0.0
var lastLon = 0.0
var result = ""
for (i in 1..positions.lastIndex) {
val elem = positions[i]
result += hereEncodeFloat(elem.latitude - lastLat)
result += hereEncodeFloat(elem.longitude - lastLon)
lastLat = elem.latitude
lastLon = elem.longitude
}
return result
}
private fun hereEncodeFloat(value: Double): String {
val chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
var result = ""
// convert to fixed point
var fixedPoint = Math.round(value * 100000)
// make room on the lowest bit
fixedPoint = fixedPoint shl (1)
// flip bits of negative numbers and ensure that the last bit is set
// (should actually always be the case, but for readability it is ok to do it explicitly)
if (fixedPoint < 0) {
fixedPoint = (fixedPoint.inv()) or 0x01
}
// var-length encode the number in chunks of 5 bits starting with the least significant
// to the most significant
while (fixedPoint > 0x1F) {
result += (chars[((fixedPoint and 0x1F) or 0x20).toInt()]).toString()
fixedPoint = fixedPoint shr (5)
}
result += (chars[fixedPoint.toInt()])
return result
}

Categories

Resources