In C++, I am trying to create a valid .bmp output file - c++

I am trying to replicate a bmp found here: https://en.wikipedia.org/wiki/BMP_file_format (its the 2x2 one). Whenever I try and open it in paint or photoviewer or whatever it says it isn't supported. I'm not sure what I am doing wrong here. I have gone over the hex values several times and everything (as far as I can tell) looks identical. Help?
#include <iostream>
#include <fstream>
using namespace std;
int main(){
ofstream bitmap;
unsigned char bm_header[14] =
/*BM*/ { 0x4D, 0x42,
/*70 bytes*/ 0x00, 0x00, 0x00, 0x46,
/*Unused */ 0x00, 0x00, 0x00, 0x00,
/* 54 bytes */ 0x00, 0x00, 0x00, 0x36 };
unsigned char dib_header[40] =
/*40 bytes*/ { 0x00, 0x00, 0x00, 0x28,
/*2 pixels wide*/ 0x00, 0x00, 0x00, 0x02,
/*2 pixels tall*/ 0x00, 0x00, 0x00, 0x02,
/*1 plane */ 0x00, 0x01,
/*24 bits */ 0x00, 0x18,
/*0 */ 0x00, 0x00, 0x00, 0x00,
/*16 bytes */ 0x00, 0x00, 0x00, 0x10,
/*2835 p/m wide*/ 0x00, 0x00, 0x0B, 0x13,
/*2835 p/m tall*/ 0x00, 0x00, 0x0B, 0x13,
/*0 colors*/ 0x00, 0x00, 0x00, 0x00,
/*0 import. colors*/0x00, 0x00, 0x00, 0x00 };
unsigned char pixel_header[16] =
{0x00, 0x00, 0xFF,
0xFF, 0xFF, 0xFF,
0x00, 0x00,
0x00, 0x00, 0xFF,
0x00, 0xFF, 0x00,
0x00, 0x00 };
bitmap.open("mandelbrot_1.bmp", ios::out | ios::binary);
for(int i = 0; i < 14; i++) {
bitmap << bm_header[i];
}
for(int i = 0; i < 40; i++) {
bitmap << dib_header[i];
}
for(int i = 0; i < 16; i++) {
bitmap << pixel_header[i];
}
cout << "success!" << endl;
bitmap.close();
return 0;
}

Each field in bm_header and dib_header is reversed from what it should be. The values 0x4d, 0x42 spell out "MB", not "BM." The sequence 0x00, 0x00, 0x00, 0x46 is interpreted as 0x46000000 bytes, not 0x46 bytes. In general the bytes in the Wikipedia table are listed in the order that they should go into the file.

Go on YouTube and search for Handmade Hero Bitmap, or go on Handmade Hero's channel and watch episodes from 36 to 39.
Casey (the author) goes over literally everything you need to know in theory and in practice down to endianness quirks and struct tight packing.
Those episodes are easy enough to consume on their own even if you have no interest in the series or haven't watched the previous episodes.

I'd suggest you do an online search for BITMAPINFOHEADER. That will give you a structure you can use instead of manipulating bytes directly.

Related

ESP32 e-Paper Image: convert from unsigned int to char array

Problem:
I am printing unsigned char array to display an image on a 7.5" waveshare e-Paper display using ESP32 with the following function:
Paint_DrawImage(const unsigned char *image_buffer, UWORD xStart, UWORD yStart, UWORD W_Image, UWORD H_Image)
That function prints an image to an e-paper display image where you also define the starting pixels (xStart, yStart) and the image size in pixels (W_Image, H_Image).
I have the code working with a sample unsigned char array below:
const unsigned char gImage_7in5_V2_b[2056] = { /* 0X00,0X01,0X20,0X03,0XE0,0X01, */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
.... not showing the whole array to save space};
There are some images that will save me a lot of time that are already converted into a similar format which is as an unsigned int with the example below:
const unsigned int icon64_50n[132]= {
0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x03000000,0x000000E0,0x1F000000,0x000000E0,0x7F000000,0x000000E0,
.... not showing the whole array to save space};
I have tried defining the array as an unsigned char but that didn't work and was really slow uploading to the ESP32 with lots of warnings.
Question:
Is this considered a byte array? I am new to this data type and need guidance on how/what to search for here.
How do I convert the unsigned int array to unsigned char?

initialize uint8_t array from txt file

I have, in a .txt file, a uint8_t array already formatted, like this:
0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
What I need is to initialize it from C++ like so:
static const uint8_t binary[] = { 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, }
Honestly, I'm a bit new at C++.
If I understand your question correctly, you simply need to include your text file at the place of array declaration:
static const uint8_t binary[] = {
#include "array.txt"
};
If the text file is shown exactly as you have shown, AND you want to initialize the array at compile-time, then you could simply #include the file, eg:
static const uint8_t binary[] = {
#include "text.txt"
}
Otherwise, you will have to open the text file at runtime, such as with std::ifstream, read in its context and parse the byte values from it, and then allocate and populate your array dynamically, such as by using std::vector.
Is the .txt file storing the hex values as bytes, or as 4 characters representing the hex values with literal commas and spaces?
If you're storing the actual hexadecimal values, the code becomes as simple as
#include <fstream>
#include <vector>
// input file stream
std::ifstream is("MyFile.txt");
// iterators to start and end of file
std::istream_iterator<uint8_t> start(is), end;
// initialise vector with bytes from file using the iterators
std::vector<uint8_t> numbers(start, end);

Trouble with Char arrays, how to properly construct and display them [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
For a product I am co-designing I want to display bitmap icons on an LCD screen. Inspired by among others this tutorial I created a separate C-file with the byte array of the icon I am trying to display.
When I try to display the icon directly it seems to work. But when I try to do it indirectly - which is going to be nessecary eventually - it fails.
What really baffles me and what I seek to understand is; when I print out the array of the garbage icon (CHAR ARRAY) to the serial monitor and compare it to the byte array it is suppose to represent they match correctly.
But when I do the same for the image that is displayed correctly (ICON ARRAY), what I print to the serial monitor does not match the byte array it is displaying, the information I printed is not even consistent... How can this be ?!
I have been cracking my head over this for a week now so any help would be greatly appreciated.
The main file:
// --------------------------------------------------------------------------------------
// | This program is made for an arduino mega 2560 used in conjunction with the |
// | (chinese) OPEN-SMART 3.2 inch TFT LCD Shield ILI9327 |
// | This version of the program is a slimmed down one to clearly convey the problem |
// | I am currenlty having drawing pictures on this setup |
// --------------------------------------------------------------------------------------
// This program is based on the library obtained from
// https://drive.google.com/open?id=0B6uNNXJ2z4CxYktCQlViUkI1Sms
// There is also a demo available on YouTube
// https://www.youtube.com/watch?v=JQHGYnKeC0M&t=2s
#include <Adafruit_GFX.h> // Core graphics library
#include <MCUFRIEND_kbv.h>
MCUFRIEND_kbv tft;
// -------------------------------------------------------------------------------------
// | Variable declaration |
// -------------------------------------------------------------------------------------
// Set colors
#define BLACK 0x0000
#define BACKGROUND 0x07FF
// No idea with this does tbh
uint16_t g_identifier;
// Spacing variables
uint8_t cube_size = 75;
uint8_t padding = 3;
uint8_t ix1 = 5+2 * padding;
uint8_t ix2 = 5+3 * padding + cube_size;
uint8_t ix3 = 5+4 * padding + 2 * cube_size;
uint8_t ix4 = 5+5 * padding + 3 * cube_size;
uint16_t ix5 = 5+(6 * padding) + 4 * cube_size;
uint8_t iy1 = 5+1 * padding;
uint8_t iy2 = 5+3 * padding + cube_size;
uint8_t iy3 = 5+4 * padding + 2 * cube_size;
//Progmem Icon init
extern uint8_t icon_from_progmem[];
// -------------------------------------------------------------------------------------
// | Functions |
// -------------------------------------------------------------------------------------
// Standard drawbitmap function
void drawBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h, uint16_t color) {
int16_t byteWidth = (w + 7) / 8; // Bitmap scanline pad = whole byte
uint8_t byte = 0;
for (int16_t j = 0; j < h; j++, y++) {
for (int16_t i = 0; i < w; i++) {
if (i & 7) byte <<= 1;
else byte = pgm_read_byte(&bitmap[j * byteWidth + i / 8]);
if (byte & 0x80) tft.drawPixel(x + i, y, color);
}
}
}
// -------------------------------------------------------------------------------------
// | Setup |
// -------------------------------------------------------------------------------------
// I just copied this part to get the screen to work
void setup(void) {
Serial.begin(9600);
Serial.println(F("TFT LCD test"));
// tft.reset(); //we can't read ID on 9341 until begin()
g_identifier = tft.readID(); //
Serial.print("ID = 0x");
Serial.println(g_identifier, HEX);
if (g_identifier == 0x00D3 || g_identifier == 0xD3D3) g_identifier = 0x9481; // write-only shield
if (g_identifier == 0xFFFF) g_identifier = 0x9341; // serial
// g_identifier = 0x9329; // force ID
tft.begin(g_identifier); //to enable ILI9327 driver code
tft.setRotation(3); //Change orientation (landscape and portrait)
}
// -----------------------------------------------------------------------------------
// | Loop |
// -----------------------------------------------------------------------------------
void loop(void) {
tft.fillScreen(BACKGROUND); //
unsigned char myCharArray[512];
byte myChar;
for (int k = 0; k < 512; k++) {
// Create myCharArray from icon_from_progmem
myChar = pgm_read_byte(icon_from_progmem + k);
myCharArray[k] = char(myChar);
// Print data from myCharArry to the serial monitor
Serial.print("CHAR ARRAY: ");
Serial.print(k);
Serial.print(" ");
Serial.println(myChar);
}
// Visual separtion string
Serial.println("------------------------------------------------------------------");
// Print data from icon_from_progmem to serial monitor
for (int k=0; k<512; k++){
Serial.print("ICONS ARRAY: ");
Serial.print(k);
Serial.print(" ");
Serial.println(icon_from_progmem[k]);
}
// Draw the two icons on the screen
drawBitmap(ix2, iy1, myCharArray, 64, 64, BLACK);
drawBitmap(ix4, iy1, icon_from_progmem, 64, 64, BLACK);
delay(600000);
} // end of void loop
The separate file for the bitmap:
#include <avr/pgmspace.h>
// 'PlafLamp', 64x64px
const unsigned char icon_from_progmem [] PROGMEM = {
0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x7f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xc0, 0x00, 0x00,
0x00, 0x00, 0x0f, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xf8, 0x00, 0x00,
0x00, 0x00, 0x7f, 0xc0, 0x03, 0xfe, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x7f, 0x00, 0x00,
0x00, 0x01, 0xfc, 0x00, 0x00, 0x3f, 0x80, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x0f, 0xc0, 0x00,
0x00, 0x07, 0xe0, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x0f, 0xc0, 0x00, 0x00, 0x03, 0xf0, 0x00,
0x00, 0x0f, 0x80, 0x00, 0x00, 0x01, 0xf0, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00,
0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00,
0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00,
0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00,
0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00,
0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00,
0x00, 0x00, 0x07, 0xc0, 0x03, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x03, 0xc0, 0x00, 0x00,
0x00, 0x00, 0x03, 0xe0, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf8, 0x1f, 0x80, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x3f, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xf8, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1c, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x7c, 0x00, 0x00,
0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x01, 0x80, 0x3f, 0x00, 0x00,
0x00, 0x01, 0xf8, 0x03, 0xc0, 0x1f, 0x80, 0x00, 0x00, 0x03, 0xf0, 0x03, 0xc0, 0x0f, 0xc0, 0x00,
0x00, 0x07, 0xe0, 0x03, 0xc0, 0x07, 0xe0, 0x00, 0x00, 0x07, 0xc0, 0x03, 0xc0, 0x03, 0xe0, 0x00,
0x00, 0x07, 0x80, 0x03, 0xc0, 0x01, 0xe0, 0x00, 0x00, 0x03, 0x00, 0x03, 0xc0, 0x00, 0xc0, 0x00,
0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00
};
What is displayed on the screen
The image on the left is the CHAR ARRAY and the image on the right is the ICON ARRAY.
in drawBitmap() you are iterating through bytes via pgm_read_byte()
In the avr-libc docs it says
Read a byte from the program space with a 16-bit (near) address.
Note:
The address is a byte address. The address is in the program space.
Your array that is a copy of the bitmap, "myCharArray", is not in program space so pgm_read_byte() does not operate correctly.

What is the best practice way to create a bitmask for a range of bits?

I can think of three ways to do this off the top of my head. I'll outline them real quick.
char mask = (1<<top)
mask = mask-1
mask = mask>>bot
mask = mask<<bot
3 shifts, 1 addition
char topMask = (1<<top)
topMask = topMask -1
char botMask = (1<<bot)
botMask = botMask - 1
char mask = topMask - botMask
2 shifts, 3 additions
char mask = (1<<(top-bot))
mask = mask - 1
mask = mask << bot
2 shifts, 2 additions
It seems like the first one would be a little faster?
Is one considered best for style reasons?
Is there a really good way I'm missing, or am I doing something stupid? Thanks!
I'd especially be interested if anyone could point me to a place this is done in the linux kernel.
EDIT:
someone posted something like this as another way and deleted it? Pretty similar to the second one. But XOR instead of subtract.
char mask = ((1<<top)-1)^((1<<bot)-1)
You could try a lookup table approach:
static const char LUT[][] = { // index like this LUT[bot][top]
//top: 0 1 2 3 4 5 6 7 8
0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF, // bot: 0
0x00, 0x00, 0x02, 0x06, 0x0E, 0x1E, 0x3E, 0x7E, 0xFE, // bot: 1
0x00, 0x00, 0x00, 0x04, 0x0C, 0x1C, 0x3C, 0x7C, 0xFC, // bot: 2
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x78, 0xF8, // bot: 3
0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x30, 0x70, 0xF0, // bot: 4
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x60, 0xE0, // bot: 5
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xC0, // bot: 6
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, // bot: 7
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // bot: 8
};
char mask = LUT[bot][top];
Also: If for whatever reason you go with bit manipulation this solution requires less ops. In addition a superscalar processor should evaluate the left and right side of the xor in parallel.
char mask = (0xFF << top) ^ (0xFF << bot);

C++ Hex Parsing

I'm wondering how to convert a hex string to a human readable string (if that makes any sense) this would be my first real encounter with hex values so I'm still learning about them and how to manage them.
I have a program which is reading in data from a file which contains raw packet data (hex) and I need to parse this information so it's human readable.
An example of what I need to do is something like this site does http://home2.paulschou.net/tools/xlate/ where you can put in hex and have it converted to text.
Taken from the C++ String Toolkit Library (StrTk) library, the following should suffice. Note that out should point to a piece of memory half the size of as std::distance(begin,end), and that the values in the range of [begin,end) be 0-9A-F or 0-9a-f
inline bool convert_hex_to_bin(const unsigned char* begin,
const unsigned char* end,
unsigned char* out)
{
if (std::distance(begin,end) % 2)
return false;
static const std::size_t symbol_count = 256;
static const unsigned char hex_to_bin[symbol_count] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x00 - 0x07
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x08 - 0x0F
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x10 - 0x17
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x18 - 0x1F
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x20 - 0x27
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x28 - 0x2F
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // 0x30 - 0x37
0x08, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x38 - 0x3F
0x00, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x00, // 0x40 - 0x47
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x48 - 0x4F
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x50 - 0x57
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x58 - 0x5F
0x00, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x00, // 0x60 - 0x67
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x68 - 0x6F
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x70 - 0x77
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x78 - 0x7F
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x80 - 0x87
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x88 - 0x8F
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x90 - 0x97
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x98 - 0x9F
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xA0 - 0xA7
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xA8 - 0xAF
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xB0 - 0xB7
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xB8 - 0xBF
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xC0 - 0xC7
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xC8 - 0xCF
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xD0 - 0xD7
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xD8 - 0xDF
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xE0 - 0xE7
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xE8 - 0xEF
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xF0 - 0xF7
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // 0xF8 - 0xFF
};
const unsigned char* itr = begin;
while (end != itr)
{
(*out) = static_cast<unsigned char>(hex_to_bin[*(itr++)] << 4);
(*out) |= static_cast<unsigned char>(hex_to_bin[*(itr++)] );
++out;
}
return true;
}
The C++-ish way to get a string containing the hexadecimal representation of a given number is to use the hex modifier for streams, as in this example:
const int i = 0xdeadbeef;
cout << "0x" << hex << i << endl; // prints "0xdeadbeef"
You can use the same modifier on string streams in case you need to have the hexadecimal representation in a string variable:
const int i = 0xdeadc0de;
ostringstream stream;
stream << "0x" << hex << i;
const string s = stream.str(); // s now contains "0xdeadc0de"
UPDATE:
If your input data is given as a string containing the hexadecimal representation of the characters of a string, you will need to know the encoding of the input string in order to display it correctly. In the simplest case, the string is something like ASCII which maps one byte to one character. So in a given input "414243", every two characters ("41", "42", "43) map to an ASCII value (65, 66, 67), which map to a character ("A", "B", "C").
Here's how to that in C++:
const string hexData = "414243";
assert( hexData.size() % 2 == 0 );
ostringstream asciiStream;
istringstream hexDataStream( hexData );
vector<char> buf( 3 ); // two chars for the hex char, one for trailing zero
while ( hexDataStream.good() ) {
hexDataStream.get( &buf[0], buf.size() );
if ( hexDataStream.good() ) {
asciiStream << static_cast<char>( std::strtol( &buf[0], 0, 16 ) );
}
}
const string asciiData = asciiStream.str(); // asciiData == "ABC"
Using std::strtol from <cstdlib> makes this easy; if you insist on using a template class for this, use std::stringstream to perform the conversion of the single sub strings (like "41") to decimal values (65).
fprintf(file, "%h", thing);
Something along those lines?
Hex is a way of displaying binary data. It is not "raw data" as you say. If the raw data you have contains a string, you should be able to see the string (possibly among other garbage) when you output it to the screen.
Here's a loop to print the ASCII characters in a block of data. To get anything else, you will have to deal with its format.
char *binary_data[ BUFFER_SIZE ];
size_t len = BUFFER_SIZE;
len = get_a_packet( data, len ); // or however you get data
for ( char *text_ptr = binary_data; text_ptr != binary_data + len; ++ text_ptr ) {
if ( * text_ptr <= '~' && * text_ptr >= ' ' ) { // if it's ascii
cerr << * text_ptr; // print it out
}
}
cerr << endl;