Convert binary two's complement data into integer in objective-c - ios

I have some binary data (twos complement) coming from an accelerometer and I need to convert it to an integer. Is there a standard library function which does this, or do I need to write my own code?
For example: I receive an NSData object from the acclerometer, which when converted to hex looks like this:
C0088001803F
Which is a concatenation of 3 blocks of 2-byte data:
x = C008
y = 8001
z = 803F
Focussing on the x-axis only:
hex = C008
decimal = 49160
binary = 1100000000001000
twos complement = -16376
Is there a standard function for converting from C008 in twos complement directly to -16376?
Thank you.

Something like:
const int8_t* bytes = (const int8_t*) [nsDataObject bytes];
int32_t x = (bytes[0] << 8) + (0x0FF & bytes[1]);
x = x << 16;
x = x >> 16;
int32_t y = (bytes[2] << 8) + (0x0FF & bytes[3]);
y = y << 16;
y = y >> 16;
int32_t z = (bytes[4] << 8) + (0x0FF & bytes[5]);
z = z << 16;
z = z >> 16;
This assumes that the values really are "big-endian" as suggested in the question.

Related

Inner product of two 16bit integer vectors with AVX2 in C++

I am searching for the most efficient way to multiply two aligned int16_t arrays whose length can be divided by 16 with AVX2.
After multiplication into a vector x I started with _mm256_extracti128_si256 and _mm256_castsi256_si128 to have the low and high part of x and added them with _mm_add_epi16.
I copied the result register and applied _mm_move_epi64 to the original register and added both again with _mm_add_epi16. Now, I think that I have:
-, -, -, -, x15+x7+x11+x3, x14+x6+x10+x2, x13+x5+x9+x1, x12+x4+x8+x0
within the 128bit register. But now I am stuck and don't know how to efficiently sum up the remaining four entries and how to extract the 16bit result.
Following the comments and hours of google my working solution:
// AVX multiply
hash = 1;
start1 = std::chrono::high_resolution_clock::now();
for(int i=0; i<2000000; i++) {
ZTYPE* xv = al_entr1.c.data();
ZTYPE* yv = al_entr2.c.data();
__m256i tres = _mm256_setzero_si256();
for(int ii=0; ii < MAX_SIEVING_DIM; ii = ii+16/*8*/)
{
// editor's note: alignment required. Use loadu for unaligned
__m256i xr = _mm256_load_si256((__m256i*)(xv+ii));
__m256i yr = _mm256_load_si256((__m256i*)(yv+ii));
const __m256i tmp = _mm256_madd_epi16 (xr, yr);
tres = _mm256_add_epi32(tmp, tres);
}
// Reduction
const __m128i x128 = _mm_add_epi32 ( _mm256_extracti128_si256(tres, 1), _mm256_castsi256_si128(tres));
const __m128i x128_up = _mm_shuffle_epi32(x128, 78);
const __m128i x64 = _mm_add_epi32 (x128, x128_up);
const __m128i _x32 = _mm_hadd_epi32(x64, x64);
const int res = _mm_extract_epi32(_x32, 0);
hash |= res;
}
finish1 = std::chrono::high_resolution_clock::now();
elapsed1 = finish1 - start1;
std::cout << "AVX multiply: " <<elapsed1.count() << " sec. (" << hash << ")" << std::endl;
It is at least the fastest solution so far:
std::inner_product: 0.819781 sec. (-14335)
std::inner_product (aligned): 0.964058 sec. (-14335)
naive multiply: 0.588623 sec. (-14335)
Unroll multiply: 0.505639 sec. (-14335)
AVX multiply: 0.0488352 sec. (-14335)

Convert double to binary representation

I'm using bit shift operators on ints to convert to binary representation like that:
String toBinary(int i) {
var bytes = Uint8List(8);
bytes[0] = i >> 56;
bytes[1] = i >> 48;
bytes[2] = i >> 40;
bytes[3] = i >> 32;
bytes[4] = i >> 24;
bytes[5] = i >> 16;
bytes[6] = i >> 8;
bytes[7] = i;
return String.fromCharCodes(bytes);
}
Now I need to do the same thing for doubles, but double does not define bit shift operators. However, as doubles are also represented in 64 bit, is there a way to convert them to binary format?
First of all Dart already provides a ByteData class so in this case you can avoid using the bit shift operation and do instead:
var byteData = ByteData(8);
byteData.setUint64(0, 256);
var bytes = byteData.buffer.asUint8List();
which will produce the same byte list.
Given that you can use the setFloat64 method on ByteData to set a double and then get the binary representation.

Preserve Color-Depth of imported Images

When importing Images with the
loadImage("...")
Command, iterating over the pixels in like this:
img.loadPixels();
int w = img.width;
int h = img.height;
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
int loc = x + y*w;
float r = red(img.pixels[loc]);
float g = green(img.pixels[loc]);
float b = blue(img.pixels[loc]);
println(r + ", " + g + ", " + b);
}
}
The R G B Values always seem to be between 0 and 255 even if the image file has a depth of 16 bit per channel, where the values should be between 0 and 65535.
Is it possible to preserve the correct color depth?
You haven't said which library the loadImage command is from.
There might be a 16-bit version, but it's unlikely. 24 bits is a sort of standard, suitable for all but very high end work.
What I suggest you do is take a look at my TIFF loader (which, like loadImage, returns 24 bit images), and modify it to return 16-bit channels. It's not difficult, just a case of not discarding the lower bits of the larger channel images (float and 16 bit).
Her'e the TIFF loader:
https://github.com/MalcolmMcLean/tiffloader

OpenCV C++: how access pixel value CV_32F through uchar data pointer

Briefly, I would like to know if it is possible to directly access pixel value
of a CV_32F Mat, through Mat member "uchar* data".
I can do it with no problem if Mat is CV_8U, for example:
// a matrix 5 columns and 6 rows, values in [0,255], all elements initialised at 12
cv:Mat A;
A.create(5,6, CV_8UC1);
A = cv::Scalar(12);
//here I successfully access to pixel [4,5]
uchar *p = A.data;
int value = (uchar) p[4*A.step + 5];
The problem is when I try to do the same operation with the following matrix,
// a matrix 5 columns, 6 rows, values in [0.0, 1.0], all elements initialised at 1.2
cv::Mat B;
B.create(5,6, CV_32FC1);
B = cv::Scalar(1.2);
//this clearly does not work, no syntax error but erroneous value reported!
uchar *p = B.data;
float value = (float) p[4*B.step + 5];
//this works, but it is not what I want to do!
float value = B.at<float>(4,5);
Thanks a lot, Valerio
You can use ptr method which returns pointer to matrix row:
for (int y = 0; y < mat.rows; ++y)
{
float* row_ptr = mat.ptr<float>(y);
for (int x = 0; x < mat.cols; ++x)
{
float val = row_ptr[x];
}
}
You can also cast data pointer to float and use elem_step instead of step if matrix is continous:
float* ptr = (float*) mat.data;
size_t elem_step = mat.step / sizeof(float);
float val = ptr[i * elem_step + j];
Note that CV_32F means the elements are float instead of uchar. The "F" here means "float". And the "U" in CV_8U stands for unsigned integer. Maybe that's why your code doesn't give the right value. By declaring p as uchar*, p[4*B.step+5] makes p move to the fifth row and advance sizeof(uchar)*5, which tend to be wrong. You can try
float value = (float) p[4*B.step + 5*B.elemSize()]
but I'm not sure if it will work.
Here are some ways to pass the data of [i, j] to value:
value = B.at<float>(i, j)
value = B.ptr<float>(i)[j]
value = ((float*)B.data)[i*B.step+j]
The 3rd way is not recommended though, since it's easy to overflow. Besides, a 6x5 matrix should be created by B.create(6, 5, CV_32FC1), I think?

How to deal with RGB to YUV conversion

The formula says:
Y = 0.299 * R + 0.587 * G + 0.114 * B;
U = -0.14713 * R - 0.28886 * G + 0.436 * B;
V = 0.615 * R - 0.51499 * G - 0.10001 * B;
What if, for example, the U variable becomes negative?
U = -0.14713 * R - 0.28886 * G + 0.436 * B;
Assume maximum values for R and G (ones) and B = 0
So, I am interested in implementing this convetion function in OpenCV,
So, how to deal with negative values?
Using float image? anyway please explain me, may be I don't understand something..
Y, U and V are all allowed to be negative when represented by decimals, according to the YUV color plane.
You can convert RGB<->YUV in OpenCV with cvtColor using the code CV_YCrCb2RGB for YUV->RGB and CV_RGBYCrCb for RGB->YUV.
void cvCvtColor(const CvArr* src, CvArr* dst, int code)
Converts an image from one color space
to another.
for planar formats OpenCV is not the right tool for the job. Instead you are better off using ffmpeg. for example
static void rgbToYuv(byte* src, byte* dst, int width,int height)
{
byte* src_planes[3] = {src,src + width*height, src+ (width*height*3/2)};
int src_stride[3] = {width, width / 2, width / 2};
byte* dest_planes[3] = {dst,NULL,NULL};
int dest_stride[3] = {width*4,0,0};
struct SwsContext *img_convert_ctx = sws_getContext(
width,height,
PIX_FMT_YUV420P,width,height,PIX_FMT_RGB32,SWS_POINT,NULL,NULL,NULL);
sws_scale(img_convert_ctx, src_planes,src_stride,0,height,dest_planes,dest_stride);
sws_freeContext(img_convert_ctx);
}
will convert a YUV420 image to RGB32

Resources