using char array to store data - c++

I need to create a program when it run it should extract a image file. to do this I I used a char array to store the data. ex:
char data[]="ÿØÿà......";
I opened the image with a hex editor and copied the data and pasted it as above. but it gives many errors. (that may be because the image data have some bytes that ascii charactors are not available. ex: nul,)
con someone give me some advices on how to do this. how to create a byte array.
thanks in eny advice.

You should use a numeric initializer instead of a string literal... for example
const unsigned char data[] = { 0x01, 0x02, 0x03, 0x04,
0x05, 0x06, 0x07, 0x08 };
A simple way is writing a small script that generates the source code by reading the file... in Python it would be something like
data = open("datafile", "rb").read()
i = 0
while i < len(data):
chunk = data[i:i+8]
print ("0x%02x, " * len(chunk)) % tuple(map(ord, chunk))
i += 8

Read the data from the file using fopen or fstream. If you want to embed the file in the exe using a resource compiler.

Related

Image File in Hex Data (RGB888) to BMP,JPG,PNG or something else

I got the following problem, that I got image files in (supposed to be RGB888) but I'm not sure if it realy is this kind of data. (I only know the supposed format (e.g. 400 * 600) of the data, that's why I made a sample data of a picture, where I exactly know which format the hex data has.)
The Data I created looks something like this:
0xf3, 0x8d, 0x4c, 0xff, 0xf2, 0x8f, 0x4b, 0xff, 0xef, ...
I'm in this case sure, that this is RGB888 because I converted it.
So the first step I did was, to load the file and stream the data to a char array.
std::ifstream infile;
char *array;
uint8_t *pixelValues;
infile.exceptions ( std::ifstream::failbit );
try {
infile.open(filename, std::ios_base::binary);
infile >> std::hex >> std::setw(2) >> std::setfill('0');
int length;
if (!infile.bad()) {
length = infile.rdbuf()->pubseekoff(0, std::ios_base::end);
array = new char[length];
infile.rdbuf()->pubseekoff(0, std::ios_base::beg);
infile.read(array, length);
infile.close();
}
uint8_t value;
pixelValues = new uint8_t[length/5];
std::size_t counter = 0;
std::size_t valueCounter = 0;
while (true) {
value = strtol(&array[counter], NULL, 0);
pixelValues[valueCounter++] = value;
while ((array[counter] != ',')) counter++;
counter++;
if (counter >= length) break;
}
}
After this step, the data in uint8_t pixelValues should be a Bitarray of the Data in the File.
My question now is, how to go on... am I doing things right or are there 'smarter' ways of getting an image out of this hex data?
My kolleague told me, that I should go on with the next step by using openCV but I can't get it running at all.
If anybody of you guys has a smart idea, please let me know ;-)
The first thing to check when someone gives you a raw image and says it is 400x600 pixels RGB888, is to look at the file size and see if it is:
400 * 600 * 3
bytes which you can check very easily before they wander off leaving you under some false impression about the format and contents. So, is your file exactly 720,000 bytes?
If you want the easiest way to get a PNG or JPEG, you would simply use ImageMagick at the command line in Terminal/Command Prompt. So, if it is 400 pixels wide and 600 pixels tall and RGB888, you would do the following to get a PNG file:
magick -depth 8 -size 400x600 RGB:YourFile.dat result.png
If you want a JPEG, use:
magick -depth 8 -size 400x600 RGB:YourFile.dat result.jpg
If you didn't feel like installing ImageMagick, you could put a NetPBM PPM header on the front of the file in Terminal, like this:
printf "P6\n400 600\n255\n" > result.ppm
cat YourImage.dat >> result.ppm
Then you will have a file that Photoshop, GIMP, feh and many other programs can read and save as PNG or JPG. Of course, you can do exactly that same thing in 3 lines of C++.
If none that appeals to you, you can use CImg - a brilliant, small, easy-to-use C++ image processing library. See here for an example.

Arduino / C Keypad Library use Byte in keymap

When I press a key on a matrix I need to send the corresponding hex value to a function. Is there any way to use a byte matrix for the keymap instead of a char one? I've tried just changing the variable type of the matrix (seen bellow) but I get all kinds of errors...
byte keys[ROWS][COLS] = {
{0xE1, 0x05, 0x06},
{0x07, 0x08, 0x09},
{0x0A, 0x0B, 0x0C},
};

C++ array with command line variable

My array looks something like this;
unsigned char send_bytes[] = { 0x0B, 0x11, 0xA6, 0x05, 0x00, 0x00, 0x70 };
One of the values is a variable that can change all the time.. so I tried something like this;
const char* input = "0x05";
unsigned char send_bytes[] = { 0x0B, 0x11, 0xA6, input, 0x00, 0x00, 0x70 };
When I compile I get a warning;
warning: initialization makes integer from pointer without a cast
I am a little confused on the conversion I need to do.. since the array has hex strings in it.. and the input string is a char..
in the first line you are declaring a pointer to const char, and initializing to the beginning of string "0x05", that's fine, but it is not the thing you are trying to do.
in the second line, you try to initialize the fourth array element (an unsigned char) with the value of the pointer you assigned to the input variable in the first line. The compiler says you are pretending to embed a pointer value (the address of "0x05" string) into a char variable, so that's why it complained. And also it is not what you intend.
also, take into account that if you are using binary data (from the fact you are initializing arrays with hex numbers) you had better to use unsigned char for binaries, as signed char is valid only for -128 to +127 values, you can expect some more unpredictable behaviour. Perhaps, a declaration typedef unsigned char byte; can do things easier.
typedef unsigned char byte;
byte send_bytes[] = { 0x0b, 0x11, 0xa6, 0x00, 0x00, 0x00, 0x70 };
byte &input = send_bytes[3]; /* input is an alias of send_bytes[3] */
BR,
Luis
Maybe explaining exactly what const char* input = "0x05"; does will clear things up for you.
First the compiler computes the string data and creates it as a static object:
const char data[5] = { 0x30, 0x78, 0x30, 0x35, 0x0 };
Then your variable is initialized:
const char *input = &data[0];
Note that input is a pointer with a value that depends entirely upon the location the compiler chooses to store the string data at, and has nothing to do with the contents of the string. So if you say char c = input; then c basically gets assigned a random number.
So you should be asking yourself "Where is the value 0x05 that I want to store in the send_bytes array?" In your code it's encoded as text, rather than as a number that your program can use directly. You need to figure out how to convert from a string of symbols following the hexadecimal scheme of representing numbers into C++'s native representation of numbers.
Here are a couple hints. Part of the operation involves associating values with each digit symbol. The symbol '0' is associated with the value zero, '1' with the value one, and so on, according to the usual hexadecimal system. Second, once you can get the associated value of a symbol, then you can use those values in some basic arithmetic operations to figure out the value of the number represented by the whole string of symbols.
For example, if you have the symbols '1' '2' and 'a', in that order from left to right then the arithmetic to compute what number is represented is 1 * 16 * 16 + 2 * 16 + 10.
The error string is pretty much telling you exactly what's wrong.
input is of type const char* (a pointer to a const char), whereas your array send_bytes is of type unsigned char[] (an array of unsigned chars).
First, signed and unsigned values are still different types, though your error message isn't referring to that specifically.
In reality, your input value isn't a string (as there is no true string type in C++), but a pointer to a character. This means that the input string doesn't hold the byte x05, but rather the bytes {x30, x78, x30, x35, x00}.
The compiler is saying Hey, I've no idea what you're trying to do, so I'm just converting the address that string I don't understand (input) to an unsigned char and adding it to the array.
That means if the string "0x05" starts at location 0xAB, your array will ultimately contain { 0x0B, 0x11, 0xA6, 0xAB, 0x00, 0x00, 0x70 }.
You're going to either have to convert from a string to an integer using a radix of 16, or just not use a string at all.
I'd also recommend reading up on pointers.
The array doesn't have "hex strings" in it - if they were, they would be enclosed in quotation marks, like all strings.
The literals are integers written in hexadecimal notation, and equivalent to
unsigned char send_bytes[] = { 11, 17, 166, input, 0, 0, 112 };
Since it's an array of unsigned char you should put an unsigned char there:
unsigned char input = 0x05;
unsigned char send_bytes[] = { 0x0B, 0x11, 0xA6, input, 0x00, 0x00, 0x70 };
You had better to put in your code:
unsigned char send_bytes[] = { 0x0b, 0x11, 0xa6, 0x00, 0x00, 0x00, 0x70 };
unsigned char &input = send_bytes[3]; /* input is an alias of send_bytes[3] */
this way you can do things like:
input = 0x26;
send_packet(send_bytes);

Why does ofstream insert a 0x0D byte before 0x0A?

I'm outputing an array of unsigned characters in C++ using ofstream fout("filename");
but it produces a spurious character in between. This is the part of the code that makes the problem:
for(int i = 0; i < 12; i++)
fout << DChuffTable[i];
and this is the definition of the array:
unsigned char DChuffTable[12] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B};
In the output file I get a spurious 0x0D between 0x09 and 0x0A. I checked the array in debugging mode right before it's going to get printed and it's not changed. Please tell me what you think of this problem.
Your stream is opening in text mode, and since 0x0A is the line feed (LF) character, that's being converted by your stream to 0x0D 0x0A, i.e. CR/LF.
Open your stream in binary mode:
std::ofstream fout("filename", std::ios_base::out | std::ios_base::binary);
Then line ending conversions should not be performed.
This is usually considered a good idea anyway, as streams can go bizarre w.r.t. flushing when in text mode.

vector of char array

I have the following code:
static unsigned char S0_gif[] = {
0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x0f, 0x00, 0x0f, 0x00, 0x91, 0x02,
..
};
It's a hex representation of a gif file. I have 500 gifs that I need to store like that so I want to use a vector to make it easier for access.
Something like:
vector<char[]> gifs;
gif.push_back( {0x47, 0x49,..} );
Then in the loop:
{
MakeImage(gif[i], sizeof gif[i] );
}
I cannot find the right code for that. Any help would be greatly appreciated.
Petry
You cant do that, because vectors store constant sized structures, and youre's are variable sized. What you can do however, is store a vector of vector :)
vector<vector<char> > gifs; // note the neccessary space between > >
gif.push_back( vector<char>( S0_gif, S0_gif + sizeof(S0_gif) ) );
Then in the loop:
{
MakeImage( gifs[i] );
}
Another idea, if they are indeed stored as static variables, is not to store the data twice:
vector< unsigned char * > gifs;
vector< size_t > gifsizes;
gifs.push_back( S0_gif );
gifsizes.push_back( sizeof(S0_gif) );
Then in the loop:
{
MakeImage( gifs[i], gifsizes[i] );
}
Disclaimer : I probably forgot some &'s, feel free to correct me.
Looks like you are storing all 500 GIF files in a row. You cannot detect size of each without parsing its header. If your function MakeImage could parse GIF header you could return pointer to the next image from it.
Then the loop will look like:
char* img_ptr = S0_gif;
while ( img_ptr ) img_ptr = MakeImage( img_ptr );
I believe that the best solution is to generate a C/CPP file that declares a vector of images. All the rest means writing code, which is not generally recommended for a lot of initialization (my opinion).
unsigned char *Array[]={
S0_gif,
S1_gif,
S2_gif,
S3_gif,
...
};
The code for generating this can be easily written in a scripting language (bash, perl, python, etc). It should be something like this:
print "char *Array[]={"
for i in range(0,500)
print "S"+i+"_gif"
print "};"
Is this a solution to your question?