Array corrupts its characters C++ - c++

I'm writing a small program for the Arduino that is able to read RGB values from a char array of HEX color codes. Let me just give you an example because it is hard to explain differently:
From the arduino serial monitor I for example send this:
/1ffffff000000
The first character tells the Arduino that this will be sequence of hex color codes. The second character tells it how many color codes there will be (it starts with 0. Thus 1 means two colors). Then the it loops trough six characters of every HEX code and adds it to the respected place in the hex[] char array. Hex[] array is two dimensional because in the first "dimension" it has the sequence number of a color and in the second it stores the RGB values of that color.
The output of this is following:
255
255
255
0
0
0
//the first part is okay, but the the second gets all messed up.
255 255 0 0 0 0 0
//the RED value of the next color gets set as the BLUE value of the previous color
And here is the code. I could't find any easier method for this idea to work. If you have suggestion on how to make this better or more efficient please let me know.
Thanks in advance!
char barva[10];
char hex[10][2];
long bluetoothVal;
bluetoothVal = Serial.read();
if (bluetoothVal == '/')
{
delay(2);
Serial.flush();
input=Serial.read();
char load = input;
int steps = load - '0';
for (int counter = 0; counter <= steps; counter++)
{
for (int i = 0; i <= 5; i++)
{
delay(2);
Serial.flush();
delay(2);
Serial.flush();
bluetoothVal=Serial.read();
char load = bluetoothVal;
barva[i] = load;
}
long int rgb = strtol(barva,0,16); //=>rgb=0x001234FE;
hex[counter][0] = (byte)(rgb>>16);
hex[counter][1] = (byte)(rgb>>8);
hex[counter][2] = (byte)(rgb);
Serial.println(hex[counter][0]);
Serial.println(hex[counter][1]);
Serial.println(hex[counter][2]);
}
for (int i = 0; i <= 1; i++)
{
Serial.println("");
Serial.println(hex[i][0]);
Serial.println(hex[i][1]);
Serial.println(hex[i-1][2]);
}
}

hex should be declared as
char hex[10][3];
You are accessing hex as hex[counter][2] = (byte)(rgb); at one place. For this you require a 10 * 3 array.

Related

Reading BMP file into an array

I am writing a longer program and I found myself needing to read a .bmp file into an array in a specific way so that the rest of the program can use it without extensive rewrites. I failed to find older answers that would resolve my problem, and I am pretty much at the beginner stages.
The image I am trying to read is used to create a text font, so I want to read it character by character into an array, where the pixels belonging to one character are added in order to a 2d bool (true if pixel is not black) array [character_id] [pixel_n]. The dimensions of characters are predetermined and known, and the file is cropped so that they all appear in a single row with no unaccounted margins.
This is the specific file I am trying to read, though here it might not show up as .bmp
As an example, shown here, I want to read the pixels in the order of the yellow line, then jump to another character. For clarity each character is 5px wide and 11px high, with 1px of margin on both sides horizontally.
Based on what I was able to find, I have written a function to do it, but I fail to make it work as intended, as far as I can tell even the pixel values are not being read correctly:
void readBMP(char* filename)
{
int i;
FILE* f = fopen(filename, "rb");
unsigned char info[54];
// read the 54-byte header
fread(info, sizeof(unsigned char), 54, f);
// extract image height and width from header
int width = *(int*)&info[18];
int height = *(int*)&info[22];
// number of pixels in total
int size = 3 * width * height;
unsigned char* data = new unsigned char[size];
// number of characters to read
int counter1 = size / ((font_width + 2) * font_height) / 3 ;
// read the rest of the data at once
fread(data, sizeof(unsigned char), size, f);
fclose(f);
//loop that goes from character to character
for(int i = 0; i < counter1; i++)
{
int tmp = 0;
//loop that reads one character into font_ref array
for(int j = 0; j < font_height; j++)
{
//loop for each row of a character
for(int k = 0; k < font_width; k++)
{
int w = static_cast<int>(data[3*(j*(font_width+2)*(counter1) + i*(font_width + 2) + 1 + k + j*font_width + j)-1]);
if( w != 0 )
font_ref [i][(tmp)] = 1;
else
font_ref [i][(tmp)] = 0;
tmp++;
}
}
}
}
(bool font_ref [150][font_width*font_height]; is the array where the font is being loaded and stored)
this code reads something, but the result is a seemingly random mess and I am unable to resolve that. Here is an example of lowercase alphabet printed using another function in the program, where white pixels represent true bools. I am aware that some libraries exist to work with graphical files, however in this program I wanted to possibly avoid that to learn more lower-level things, and the goal is rather limited and specific.
Thank you in advance for any help with the issue.
The main errors are in the offset computation for a pixel in the bitmap data:
int w = static_cast<int>(data[3*(j*(font_width+2)*(counter1) + i*(font_width + 2) + 1 + k + j*font_width + j)-1]);
j*(font_width+2)*(counter1) - This doesn't take into account that
although you say the file is cropped, there is extra black space to the right of the last character cell, so the true width must be used;
(as drescherjm and user3386109 mentioned) padding bytes are appended to the rows so that their length is a multiple of four bytes.
+ j*font_width + j)-1 - This part makes no sense - perhaps you tried to compensate the above errors.
This would be correct:
int w = data[j*(3*width+3&~3)+3*(i*(font_width+2)+1+k)];

Arduino c+ >> operation

I am adapting the example for the Arduino AutoAnalogAudio library entitled
SDAudioWavPlayer
which can be found in Examples->AutoAnalogAudio->SDAudio->SDAudioWavPlayer
This example uses interrupts to repeatedly call the function
void loadBuffer(). The code for that is below
/* Function called from DAC interrupt after dacHandler(). Loads data into the dacBuffer */
void loadBuffer() {
if (myFile) {
if (myFile.available()) {
if (aaAudio.dacBitsPerSample == 8) {
//Load 32 samples into the 8-bit dacBuffer
myFile.read((byte*)aaAudio.dacBuffer, MAX_BUFFER_SIZE);
}else{
//Load 32 samples (64 bytes) into the 16-bit dacBuffer
myFile.read((byte*)aaAudio.dacBuffer16, MAX_BUFFER_SIZE * 2);
//Convert the 16-bit samples to 12-bit
for (int i = 0; i < MAX_BUFFER_SIZE; i++) {
aaAudio.dacBuffer16[i] = (aaAudio.dacBuffer16[i] + 0x8000) >> 4;
}
}
}else{
#if defined (AUDIO_DEBUG)
Serial.println("File close");
#endif
myFile.close();
aaAudio.disableDAC();
}
}
}
The specific part I am concerned with is the second part of the if statement
{
//Load 32 samples (64 bytes) into the 16-bit dacBuffer
myFile.read((byte*)aaAudio.dacBuffer16, MAX_BUFFER_SIZE * 2);
//Convert the 16-bit samples to 12-bit
for (int i = 0; i < MAX_BUFFER_SIZE; i++) {
aaAudio.dacBuffer16[i] = (aaAudio.dacBuffer16[i] + 0x8000) >> 4;
}
}
Despite the comment MAX_BUFFER_SIZE is 256 so 512 bytes are read into
aaAudio.dacBuffer16. That data was originally 16 bit signed integers (+/- 32k) and dacBuffer16 is an array of 16bit unsigned integers (0-64K). The negative sign is removed by going through the array and adding 2^15 (0x8000) to each element. This makes the negative numbers overflow leaving the positive part of the negative number. Positive numbers are just increased by 2^15. thus the values are rescalled to lie in 0 -64K. The result is then shifted 4 places right so that only the highest 12 bits remain which is what the Arduino DAC can handle. This all happens in the line
aaAudio.dacBuffer16[i] = (aaAudio.dacBuffer16[i] + 0x8000) >> 4;
So far so good.
Now I want to be able to programmatically reduce the volume. As far as I can find the library does not provide a function to do that so I thought that the simplest
thing to do was to change the '4' to 'N' and increase the amount of shifting to 5,6,7.. etc
eg
aaAudio.dacBuffer16[i] = (aaAudio.dacBuffer16[i] + 0x8000) >> N;
where N is an integer. I tried this but I got a terribly distorted result which I did not understand.
While fiddling around trying different things I tried the following which works
uint16_t sample;
int N = 5;
for (int i = 0; i < MAX_BUFFER_SIZE; i++)
{
sample = (aaAudio.dacBuffer16[i] + 0x8000);
sample = sample >> N;
// sample = sample / 40;
aaAudio.dacBuffer16[i] = sample;
}
You can also see that I have commented out simply dividing by a number which works if I want finer control.
My problem is I do not see what the difference is between the two bits of code.
Can anybody enlighten me ?

C++ - Trying to read a .PPM image, unexpected output

I'm developing a uni project for reading the image data of P6-type, 255-depth .ppm images. The problem I encounter is that when I try to print the average values of each color (R,G,B) for an Image, the output I get is wrong (the proffessor has given us an output file which says what float values to expect for each given image).
Now, I'm at a loss here. Through many checks, I have concluded that the function reads the whole data from the image, without leaving out pixels or whatever, converts them correctly from 0-255 to 0.f - 1.f values (by dividing with 255.0), adds every red, every green and every blue value to three seperate counters and then divides them by the Width*Height of the given image to get the desired average brightness of each colour. I will provide part of the function that does this process for calculating the average red for a 960*642 Image (sorry for the hardcoded stuff, it's just there for debugging purposes).
The output I get for this is 0.58... when it should be 0.539068. seekg() is called with 14 as an argument because position 14 is the last space after the header and before the data. Could you provide any insight to why this isn't working as expected? One thing I found through the checks is the sum I get after adding all the red float values, is not a float but an int. Possible loss of data? I'm grasping at straws here.
Here is the code:
std::ifstream infile;
infile.open("Image02.ppm", std::ios::in | std::ios::binary);
const unsigned char* buffer;
float * data_ptr;
infile.seekg(0, std::ios::end);
int length = infile.tellg(); //calculating length of data
buffer = new unsigned char[length];
ptr = new unsigned char[length];
data_ptr = new float[length];
infile.seekg(14, std::ios::beg); //restoring pointer to the start of data stream
infile.read((char*)buffer, length); //reading the image
for (int i = 0; i < length; i++){ //casting the char data to floats to get the 0-255 values
data_ptr[i] = ((float)buffer[i]);
data_ptr[i] = data_ptr[i] / 255.f; // converting to 0.0 - 1.0
}
int j = 0;
float a = 0.f;
while (j < length){ //calculating sum of red pixel values
a = a + data_ptr[j];
j = j + 3;
}
std::cout << a / (960*642); //calculating average
FYI, PPM image files that are P6 have their image data stored from left to right, with the first line being line 0 and the last line of the image being the last. They are structured like this R G B R G B R G B so on, where the first RGB correspond to the first pixel and so forth.
Thanks in advance!
You need pixels only for average calculation.
But in your source code, additional 14 garbage values are being used.

pad print line with white space C++

In C++ I am using unsigned char pointers to hold byte arrays so that I can fit 8 bit color codes in each element for a print line.
I have one array holding data, and one array holding white space, and I am using for loops to populate a third array so that the data is at the beginning and white space is at the end.
When the pointer is created, as I monitor memory at runtime, all elements have a default value of 0xCD, which is magenta on color chart. I use a for loop to populate the bytes I want with 0x00, but it will not write over the default array value of the third array.
So, I am stuck with my printer printing magenta instead of white space. Yet I can write over that array just fine with just the data. But not with the whitespace. Im unsure what is the reason for that. Can anyone give me any insight? Here is my code...
PrintLine(unsigned char* pbData, unsigned long ulDataSize, UINT xoffset)
{
if (xoffset > 0)
{ //create pointer to byte array for xoffset
unsigned char* offsetData;
offsetData = new unsigned char[(xoffset / 8)]; //x offset is divided by 8
//to convert pixels to bytes
//create pointer to byte array to hold image data and offset data
unsigned char* finalData;
finalData = new unsigned char[ulDataSize + (xoffset / 8)];
//begin final data with image data passed into the function
for (int count = 0; count < ulDataSize; count++)
{
finalData[count] = pbData[count];
}
//populate offset data with blank bytes
for (int count = 0; count < (xoffset / 8); count++)
{
offsetData[count] = 0x00;
}
//add blank data for offset to finalData
int position = 0;
for (int count = ulDataSize; count < ulDataSize + (xoffset / 8);count++)
{
finalData[ulDataSize] = offsetData[position];//also tried =0x00
position++;
}
//Send data to printer.
if (!(Write(finalData, ulDataSize + (xoffset / 8)))
{
return FALSE;
}
return TRUE;
}
}
At first glance your code don't have errors, but I see something that looks suspicious. I'm talking about the line:
finalData[ulDataSize] = offsetData[position]; //also tried =0x00
I think what you want is:
finalData[count] = offsetData[position];//also tried =0x00
On the other hand you could write your loop like this:
for (int count = 0; count < (xoffset / 8); count++)
{
finalData[ulDataSize + count] = offsetData[count];
}
Making the code much more readable.

BMP file format not read properly?

Hey folks!
I got this image.bmp.
When i read it with all padding included and such i get this result.
What am i doing wrong here besides reading the image upside down? I don't find anything relative on Wikipedia or by googling. It seems that after 24 pixels width the image is mirrored 8 pixels. Why!? I don't get it!? How can i fix this!?
I'm reading the file with some C++ code on Windows reading the BMP file raw.
The image file is monochrome. 1 bit per pixel.
Code for showing bitmap data:
unsigned int count = 0; // Bit counting variable
unsigned char *bitmap_data = new char[size]; // Array containing the raw data of the image
for(unsigned int i=0; i<size; i++){ // This for-loop goes through every byte of the bitmap_data
for(int j=1; j<256; j*=2){ // This gives j 1, 2, 4, 8, 16, 32, 64 and 128. Used to go through every bit in the bitmap_data byte
if(count >= width){ // Checking if the row is ended
cout << "\n"; // Line feed
while(count > 32) count -=32; // For padding.
if(count < 24) i++;
if(count < 16) i++;
if(count < 8) i++;
count = 0; // resetting bit count and break out to next row
break;
}
if(i>=size) break; // Just in case
count++; // Increment the bitcounter. Need to be after end of row check
if(bitmap_data[i] & j){ // Compare bits
cout << (char)0xDB; // Block
}else{
cout << (char)' '; // Space
}
}
}
Thanks in advance!
You are almost certainly interpreting/outputting the bits in the wrong order in each byte. This results in each column of 8 pixels being flipped left to right.
The BMP format states that the left-most pixel is the most significant bit, and the right-most pixel is the least. In your code, you are iterating the wrong way through the bits.