0

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 ;-)

Miki
  • 40,887
  • 13
  • 123
  • 202
freak228
  • 33
  • 8
  • [Saving a simple image buffer to png in C++](//stackoverflow.com/a/2289638) – 001 Dec 11 '18 at 13:32
  • It's unclear what is the width and height of the image. You have `length` but I can't tell what that represents. `length/5` is also a mystery. OpenCV is overkill for saving image to png, but it will work. If you are having problems running OpenCV then investigate that separately. – Barmak Shemirani Dec 12 '18 at 06:43
  • length is the amount of characters... as the values of the input file gets saved in the format: array[0] = '0' array[1] = 'x' array[2] = 'f' array[3] = '3' array[4] = ',' array[5] = ' ' array[6 to end] = and so on .... as there is always a minimum of 4 letters and minimum one ',' i divide by 5 as I don't know if there is any whitespace. valueCounter in the end will be the true length amount. It's just to save enough space. width and height are known values. – freak228 Dec 12 '18 at 14:41
  • It seems you are writing to the file in plain text format "0xf3, 0x8d,..." then you read it binary mode using `fstream::read`. In text mode you are using 5 character to represent one byte. But in binary, each byte takes one byte, not 5 bytes. Either write in text mode and read in text mode, or write in binary and read in binary. The latter is recommended. – Barmak Shemirani Dec 13 '18 at 01:17

1 Answers1

1

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.

Mark Setchell
  • 191,897
  • 31
  • 273
  • 432
  • 1
    Thanks for your respond! Can you tell me more about the three lines of code? – freak228 Dec 17 '18 at 11:25
  • I'm not at a proper computer, but you open a file called `result.ppm` for write and write the `P6\n400...` stuff into that file. Then you write the entirety of your array to the file directly after the header and close it. That's all. – Mark Setchell Dec 17 '18 at 11:29