0

I have the following code:

#include <Magick++.h>
#include <iostream>
#include <fstream>

using namespace Magick;
using namespace std;

unsigned short int version = 1;
unsigned short int cols, rows;
short int myCol, myRow;

int main(int argc, char **argv) {
  ofstream myFile;
  myFile.open("img001.bin", ios::out | ios::trunc | ios::binary);
  myFile.write(reinterpret_cast<const char*> (&version), sizeof(version));

  try {
    InitializeMagick(*argv);
    Image img("noname-th.jpg");
    cols = img.columns();
    rows = img.rows();
    myFile.write(reinterpret_cast <const char*> (&cols), sizeof(cols));
    myFile.write(reinterpret_cast <const char*> (&rows), sizeof(rows));

    for (myCol = cols - 1; myCol >= 0; myCol--) {
      for (myRow = rows - 1; myRow >= 0; myRow--) {
        ColorRGB rgb(img.pixelColor(myCol, myRow));
        cout << "red: "     << (rgb.red()   * 255);
        cout << ", green: " << (rgb.green() * 255);
        cout << ", blue: "  << (rgb.blue()  * 255) << endl;
      }
    }
  }
    catch ( Magick::Exception & error) {
    cerr << "Caught Magick++ exception: " << error.what() << endl;
  }
  return 0;
}

This works great in that it spits out the values for me to see (and make sure it's doing the right thing.) Note: yes, I am aware that it's starting at the lower right corner and reading down to 0,0. That's the intention here.

What I need now is figure out how to write those rgb values to the open file. For each pixel, I get the values from rgb.red() * 255, rgb.green() * 255, and rgb.blue() * 255. How do I store those as r,g,b (one pixel per line) in the file?

I think I need to do the same char casting on them, but I don't know how to get them concatenated together on a single line. Each file.write() automatically add an LF at the end.

Thanks.

5
  • Check out en.cppreference.com/w/cpp/io/basic_ostream/write Commented Jun 11, 2013 at 22:03
  • Thanks for the suggestion. I guess what I'm not understanding is how to tie them together as one string (separated by commas) and then writing it out. I can write out the single values just fine (after casting to char*), but I'm unsure how to do all three as a single line in the file. Commented Jun 11, 2013 at 22:12
  • Are you writing a text file or a binary file? If it is binary, then why do you need to separate the values with commas? Commented Jun 11, 2013 at 22:18
  • p.s. You should declare your variables local to main(). Usually global variables are frowned upon, unless you have a specific reason for using them. Commented Jun 11, 2013 at 22:24
  • You should change that endl to a \n or what ever newline you want to go with. endl flushes, which is not good in such a large loop. You can flush the stream after the loop using flush. just a tip. Commented Jun 11, 2013 at 22:27

2 Answers 2

1

I am going to assume that rgb.red(), etc. all return int. If so, then you can write these values in exactly the same way that you wrote the number of columns and rows:

int red = (int)(rgb.red() * 256);
myFile.write(reinterpret_cast <const char*> (&red), sizeof(red));

Note that binary files do not have any concept of LF or CR. They only contain binary data which you interpret by read() and write() calls.

Sign up to request clarification or add additional context in comments.

12 Comments

Actually no, $rgb.color() returns a float (between 0 and 1) which is why it's being multiplied by 255 to get a value between 0 and 255. But, you mentioned something else in an earlier comment, why separate with commas. I don't have an answer for that. I'm used to seeing (ascii) data separated by commas so that was an assumption that I made, that I need to do the same thing here. I guess I'll write it as is and go from there. Thanks for the pointers.
@KirAsh4 You need to decide whether you want to output your data as ASCII text (in which case separating numbers with commas certainly makes sense) or as binary (in which case commas are unnecessary). You also need to decide whether you want to output a color value as a floating point number between 0.0 and 1.0 or as an integer between 0 and 255. Either way, the code I have given above will work for writing binary data. Simply change int red to float red and, optionally, multiply by 256.
I'm writing binary, so nix the whole comma thing. And I need to write the ints between 0 and 255, hence the multiplication in my code above. 255 is the correct value for this, not 256.
@KirAsh4 Does rgb.color() return a value in the closed, open, half-open interval between 0.0 and 1.0?
pixel (0,0) => red: 0.203922, green: 0.196078, blue: 0.207843
|
1

Binary files do not have the concept of 'newlines' or lines. They are only for text files to make it readable to us mortal humans. So in that sense, you don't need to worry about newlines. Keep writing the binary color values to the file. The only thing you should be concerned about is who is consuming this file and if the binary format you're using to write to the file is acceptable to that consumer.

1 Comment

The "consumer" is me. This is converting an image file to the respective rgb values for every pixel. That data file then goes on an SD card which an Arduino will then access and pull the data back out and push to a string of LEDs. This is but step 1 out of a much larger piece.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.