convert 16 bit Infrared data to meaningful data in C/Objective C - objective-c

I have an API that returns the 16-bit Infrared data from a file.
The usage is like this:
UInt16 *irDataResult = IrbGetIrData16([self.path UTF8String]);
The length of the the data pointed by the pointer is : 1024x768x2.
I want to convert it in to an int 2 dimensional array so that I have individual pixels and then I can use one of the UIImage functions to create image out of my raw data.
The I way I'm doing is this:
int dataArray[width][height];
int *dataPointer = &dataArray[0][0];
int byteNum = 0;
for (int w = 0; w < width; w++) {
for (int h = 0; h < height; h++) {
dataArray[w][h] = irDataSource[byteNum] <<0 | irDataSource[byteNum] << 8; //Little endian
byteNum++;
}
}
The loop runs fine, but after a little while it gives my BAD_ACCESS error.
What am I doing wrong?
Also, is this the right approach?

Related

MLX90621 no Acknowlegde with the RAM

First off all I am a beginner regarding embedded programming.
For an application I do want to use the MLX90621 thermo pixel array togehter with an STM32G431KB. On the Melexis Website is an example Code with some sort off abstraction. I moddified the lowlevel part of the code to work with the HAL library of the MCU.
For some reason I can read the EEPROM and write to it, get an acknowledge... But when trying to read from the adress 0x60, the RAM, where the sensorvalues are stored i do not get an acknowledge. I do have checkt with an logic analyer and I am sending the correct messages. Just for refference I do have added the code part of the read function.
Has anybody an idea regarding some very dump timing error or something like that.
P.S. Allready tried an different sensor of my order with the exact same result.
int MLX90621_I2CRead(uint8_t slaveAddr,uint8_t command, uint8_t startAddress, uint8_t addressStep, uint8_t nMemAddressRead, uint16_t *data)
{
uint8_t sa = slaveAddr << 1;
int cnt = 0;
int i = 0;
uint8_t cmd[4] = {0,0,0,0};
uint8_t i2cData[132] = {0};
uint16_t *p;
p = data;
cmd[0] = command;
cmd[1] = startAddress;
cmd[2] = addressStep;
cmd[3] = nMemAddressRead;
if (HAL_I2C_Master_Transmit(&hi2c2, sa, cmd, 4, HAL_MAX_DELAY) != HAL_OK)
return -1;
HAL_Delay(1);
//sa = sa | 0x01;
//ack = i2c.read(sa, i2cData, 2*nMemAddressRead, 0);
if (HAL_I2C_Master_Receive(&hi2c2, sa, i2cData, 2*nMemAddressRead, HAL_MAX_DELAY) != HAL_OK)
return -1;
for (cnt = 0; cnt < nMemAddressRead; cnt++) {
i = cnt << 1;
*p++ = (uint16_t)i2cData[i+1]*256 + (uint16_t)i2cData[i];
}
return 0;
}

How to covert Textbox to integer array in c++/cli

I'm trying to convert the textbox to an integer array assuming that every character of the textbox is a digit.
//textbox is named input
int size = this->input->Text->Length;
int * num = new int[size];
int Counter = 0;
//for loop used since textbox inputs like a calculator
//Ex: the number: 234 is inputed: 2, then 23, then 234
for (int i = size; i > 0; i--)
{
num2[Counter] = System::Convert::ToInt32(input->Text[i-1]);
Counter += 1;
}
Array of numbers should be:
num[0] = 4, num[1] = 3, num[2] = 2
Upon research though it seems that it's finding the integer unicode value instead.
Code input->Text[i-1] returns a single Unicode character value of the wchar_t type. That is implicitly cast to Int32, i.e. the symbol code.
You have to convert the char to a string, before converting to the number. You can use the Substring method or the ToString method for this purpose.
You can do it as follows:
String^ text = this->input->Text;
int size = text->Length;
int * num = new int[size];
for (int i = size - 1; i >= 0; i--) {
num[i] = Convert::ToInt32(text->Substring(size - i - 1, 1));
}
However, you should not mix managed and unmanaged code.
There is a better way. Use a generic collection instead of an array.
String^ text = this->input->Text;
int size = text->Length;
List<int>^ nums = gcnew List<int>();
for (int i = size - 1; i >= 0; i--) {
nums->Add(Convert::ToInt32(text[i].ToString()));
}
Don't forget
using namespace System::Collections::Generic;
The list can be accessed by index like an array:
nums[i]
So it is convenient to work with. And most importantly, do not need to worry about freeing memory.

Check if image is dark-only bottom part

I am checking if UIImage is darker or more whiter . I would like to use this method ,but only to check the third bottom part of the image ,not all of it .
I wonder how exactly to change it to check that,i am not that familiar with the pixels stuff .
BOOL isDarkImage(UIImage* inputImage){
BOOL isDark = FALSE;
CFDataRef imageData = CGDataProviderCopyData(CGImageGetDataProvider(inputImage.CGImage));
const UInt8 *pixels = CFDataGetBytePtr(imageData);
int darkPixels = 0;
long length = CFDataGetLength(imageData);
int const darkPixelThreshold = (inputImage.size.width*inputImage.size.height)*.25;
//should i change here the length ?
for(int i=0; i<length; i+=4)
{
int r = pixels[i];
int g = pixels[i+1];
int b = pixels[i+2];
//luminance calculation gives more weight to r and b for human eyes
float luminance = (0.299*r + 0.587*g + 0.114*b);
if (luminance<150) darkPixels ++;
}
if (darkPixels >= darkPixelThreshold)
isDark = YES;
I can just crop that part of the image, but this will be not efficient way, and wast time .
The solution marked correct here is a more thoughtful approach for getting the pixel data (more tolerant of differing formats) and also demonstrates how to address pixels. With a small adjustment, you can get the bottom of the image as follows:
+ (NSArray*)getRGBAsFromImage:(UIImage*)image
atX:(int)xx
andY:(int)yy
toX:(int)toX
toY:(int)toY {
// ...
int byteIndex = (bytesPerRow * yy) + xx * bytesPerPixel;
int byteIndexEnd = (bytesPerRow * toY) + toX * bytesPerPixel;
while (byteIndex < byteIndexEnd) {
// contents of the loop remain the same
// ...
}
To get the bottom third of the image, call this with xx=0, yy=2.0*image.height/3.0 and toX and toY equal to the image width and height, respectively. Loop the colors in the returned array and compute luminance as your post suggests.

Accessing my malloc'd 2d array with [x][y]

I'm updating a class to use member variable instead of #defines to define the bounds of a 2d array. It used to look like:
#define kWidth 3
#define kHeight 100
NSUInteger fields[kWidth][kHeight];
Now kWidth and kHeight are iVars. I switched to malloc convention, because I see no other choice as the bounds can now change. The problem is I cannot access the array using two [] ([][]). See my inline comments. I am sure I've malloc'd correctly. I've done this many times before, and under iOS. Why can't I access this way?
self.kFieldsHeight = 100;
self.kFieldsWidth = 3;
NSUInteger** fields = (NSUInteger**)malloc(sizeof(NSUInteger) * self.kFieldsHeight * self.kFieldsWidth);
memset(fields, 0xFF, self.kFieldsWidth * self.kFieldsHeight * sizeof(NSUInteger));
//// Now with LLDB I can examine the array in one dimension
// p fields[0] // 0xFFFFFFFF
// p fields[299] // 0xFFFFFFFF
// p fields[300] // 0xGARBAGE
//// THIS fails with "error: Couldn't dematerialize struct : Couldn't read a composite type from the target: gdb remote returned an
error: E08"
// p fields[0][0]
// Thus this fails in my code
NSUInteger i = fields[0][0];
What's the deal?
Edit: (more detail)
I've also tried mallocing like this:
fields = (NSUInteger**)malloc(sizeof(NSUInteger*) * self.kFieldsHeight);
if(fields){
for(int i = 0; i < self.kFieldsHeight; i++){
fields[i] = (NSUInteger*)malloc(sizeof(NSUInteger) * self.kFieldsWidth);
}
}
Edit: (even more detail). I swapped the width and height with the same results:
fields = (NSUInteger**)malloc(sizeof(NSUInteger*) * self.kFieldsWidth);
if(fields){
for(int i = 0; i < self.kFieldsWidth; i++){
fields[i] = (NSUInteger*)malloc(sizeof(NSUInteger) * self.kFieldsHeight);
}
}
You need to do this:
NSUInteger **fields = malloc(self.kFieldsHeight * sizeof(NSUInteger*));
for (int i = 0; i < self.kFieldsHeight; i++) {
fields[i] = malloc(sizeof(NSUInteger) * self.kFieldsWidth);
memset(fields, 0xFF, self.kFieldsWidth * sizeof(NSUInteger));
}
But this is not the way most people do the job. Most developers use a big array instead of a 2d array and try to index it themselves. Like this:
NSUInteger *fields = malloc(self.kFieldsHeight * self.kFieldsHeight * sizeof(NSUInteger));
fields[h * width + w] = pixel_value;
try this
fields = (NSUInteger**)malloc(sizeof(NSUInteger*) * self.kFieldsWidth);
if(fields){
for(int i = 0; i < self.kFieldsWidth; i++){
fields+i = (NSUInteger*)malloc(sizeof(NSUInteger) * self.kFieldsHeight);
}
}
no real reason for doing it this way, just another way of saying a[i] is a+i
I am using my C knowledge here and not objective C hope I can help

Using memcpy and malloc resulting in corrupted data stream

The code below attempts to save a data stream to a file using fwrite. The first example using malloc works but with the second example the data stream is %70 corrupted. Can someone explain to me why the second example is corrupted and how I can remedy it?
short int fwBuffer[1000000];
// short int *fwBuffer[1000000];
unsigned long fwSize[1000000];
// Not Working *********
if (dataFlow) {
size = sizeof(short int)*length*inchannels;
short int tmpbuffer[length*inchannels];
int count = 0;
for (count = 0; count < length*inchannels; count++)
{
tmpbuffer[count] = (short int) (inbuffer[count]);
}
memcpy(&fwBuffer[saveBufferCount], tmpbuffer, sizeof(tmpbuffer));
fwSize[saveBufferCount] = size;
saveBufferCount++;
totalSize += size;
}
// Working ***********
if (dataFlow) {
size = sizeof(short int)*length*inchannels;
short int *tmpbuffer = (short int*)malloc(size);
int count = 0;
for (count = 0; count < length*inchannels; count++)
{
tmpbuffer[count] = (short int) (inbuffer[count]);
}
fwBuffer[saveBufferCount] = tmpbuffer;
fwSize[saveBufferCount] = size;
saveBufferCount++;
totalSize += size;
}
// Write to file ***********
for (int i = 0; i < saveBufferCount; i++) {
if (isRecording && outFile != NULL) {
// fwrite(fwBuffer[i], 1, fwSize[i],outFile);
fwrite(&fwBuffer[i], 1, fwSize[i],outFile);
if (fwBuffer[i] != NULL) {
// free(fwBuffer[i]);
}
fwBuffer[i] = NULL;
}
}
You initialize your size as
size = sizeof(short int) * length * inchannels;
then you declare an array of size
short int tmpbuffer[size];
This is already highly suspect. Why did you include sizeof(short int) into the size and then declare an array of short int elements with that size? The byte size of your array in this case is
sizeof(short int) * sizeof(short int) * length * inchannels
i.e. the sizeof(short int) is factored in twice.
Later you initialize only length * inchannels elements of the array, which is not entire array, for the reasons described above. But the memcpy that follows still copies the entire array
memcpy(&fwBuffer[saveBufferCount], &tmpbuffer, sizeof (tmpbuffer));
(Tail portion of the copied data is garbage). I'd suspect that you are copying sizeof(short int) times more data than was intended. The recipient memory overflows and gets corrupted.
The version based on malloc does not suffer from this problem since malloc-ed memory size is specified in bytes, not in short int-s.
If you want to simulate the malloc behavior in the upper version of the code, you need to declare your tmpbuffer as an array of char elements, not of short int elements.
This has very good chances to crash
short int tmpbuffer[(short int)(size)];
first size could be too big, but then truncating it and having whatever size results of that is probably not what you want.
Edit: Try to write the whole code without a single cast. Only then the compiler has a chance to tell you if there is something wrong.