raytracing.github.io
raytracing.github.io copied to clipboard
Can't open created ppm file (PPM must be ASCII or UTF-8)
I've just started reading/implementing Ray Tracing in One Weekend and already stumbled upon this problem. This is my c++ code:
int main() {
const int image_width = 256;
const int image_height = 256;
std::cout << "P3\n" << image_width << ' ' << image_height << "\n255\n";
for (int y = image_height-1; y >= 0; --y) {
std::cerr << "\rScanlines remaining: " << y << ' ' << std::flush;
for (int x = 0; x < image_width; ++x) {
auto r = double(x) / (image_width-1);
auto g = double(y) / (image_height-1);
auto b = 0.25;
int ir = static_cast<int>(255.999 * r);
int ig = static_cast<int>(255.999 * g);
int ib = static_cast<int>(255.999 * b);
std::cout << ir << ' ' << ig << ' ' << ib << '\n';
}
}
}
And this is the output in the .ppm file:
P3 256 256 255 0 255 63 1 255 63 2 255 63 3 255 63 4 255 63 5 255 63 6 255 63 7 255 63 8 255 63 9 255 63 10 255 63 ...
Tried opening this with Gimp, XNView and IrfanView but they all can't seem to read the file.
From the book:
Opening the output file (in ToyViewer on my Mac, but try it in your favorite viewer and Google “ppm viewer” if your viewer doesn’t support it) ...
I use ImageMagick personally, but there are other results.
I'm on Windows by the way... I installed ImageMagick and still get this error: "Improper image header".
I've searched for information about the ppm header and I don't see any differences compared to mine so I'm not sure what's happening.
Attached a PPM file that you should be able to view. You'll need to rename the extension from .txt to .ppm (GitHub restricts uploads to a small set of acceptable file extensions).
Is your file written out with a Unicode BOM perhaps? Here are the first bytes of the attached PPM file:
50330d0a 32302031 310d0a32 35350d0a # 00000000 P3..20 11..255..
32323020 32333520 3235350d 0a323230 # 00000010 220 235 255..220
20323335 20323535 0d0a3232 30203233 # 00000020 235 255..220 23
35203235 350d0a32 32302032 33352032 # 00000030 5 255..220 235 2
35350d0a 32323020 32333520 3235350d # 00000040 55..220 235 255.
0a323230 20323335 20323535 0d0a3232 # 00000050 .220 235 255..22
30203233 35203235 350d0a32 32302032 # 00000060 0 235 255..220 2
33352032 35350d0a 32323020 32333520 # 00000070 35 255..220 235
3235350d 0a323230 20323335 20323535 # 00000080 255..220 235 255
0d0a3232 30203233 35203235 350d0a32 # 00000090 ..220 235 255..2
(Note that you should be able to use either LF or CRLF line endings.)
I reran your code, on windows, and got a ppm that I was able to view in FastStone
You could also rename your PPM output file to have a .txt
extension, and upload it here so we can try it out on our end.
@hollasch Thanks! The file you sent does work on my end.
I attached my generated .ppm
Maybe some more needed information: I built my .exe with Visual Studio 2019 with no special settings.
Yup. Your file is UTF-16 with BOM. It should be UTF-8 or ASCII with no BOM.
Image looks good when converted to UTF-8 no BOM.
Ok great! So I assume this has something to do with the Visual Studio project settings? I'm going to search on how to set the output format.
Ugh. Now I'm not confident that I know how my code's working. :)
I thought it would be a project setting, but then I just read that the text output is indeed UTF-8, but the Windows console transforms this to UTF-16. I remember getting this same result in another project, and ended up (for a while) setting my codepage to Unicode to fix this.
You can change the codepage in a Windows command shell with the chcp
command. By default it's 437; Unicode is 65001. As an experiment, run the command chcp 65001
, and then try re-running your program and redirecting the output into your x.ppm output file, then see if that is readable (is UTF-8 no-bom).
There's also mention of the Windows API SetConsoleOutputCP(CP_UTF8);
(include windows.h) to do this programatically.
Still I don't know why this is all working for me, as I'm doing none of these things. It's possible that CMake is fixing this for me, by supplying the Visual Studio /utf8
compiler option.
I don't see any obvious Unicode or UTF-8 mentions in the CMake-generated .vcxproj
files.
Ok, I tried it but it wasn't working. This gave me an idea however. I was running the executable from a PowerShell window inside Visual Studio. I tried running it from a regular CMD window and that fixed the issue.
Sigh.
Without too much work, you could alter the program to take an output image filename on the command line and create the file directly. Or just take your workaround and carry on.
However, it's useful to note that the program/build wasn't the issue, it was the environment inducing the encoding change.
I can open a CMD window inside VS so it's not really an issue at the moment. And yes, I assumed it was going to be something like that. This might be good to add as a note in the book. Anyway, @hollasch, thank you very much for helping me out! :)
Glad to help. We have kicked around the idea of general system-specific notes. This would indeed be a good candidate entry. I'm leaving this open, assigned to a future milestone.
Same problem, thanks for helping me track this down. This is what fixed it for me with Powershell on Windows. Based on some stack overflow posts this is a problem lots of people have with Powershell for various text outputs:
PS: C:\raytracing\main\Release> main.exe | set-content image.ppm -encoding String
I tried -encoding UTF8
and -encoding Unicode
but those didn't work.
Maybe this should get spun out into a discussion? I'm not sure what the issue to solve here is?
Since this is such a basic requirement for our project, it warrants a quick mention somehow. In the past, we talked about developer notes for various platforms, but for now we can just mention generally that if you can't see the image, you should check the actual emitted bytes somehow, since all of the rest depends on being able to view the resulting images.
Revisiting this, I like Trevor's suggestion. I'll seed a discussion, and then point to it from a very short comment in the book.
See discussion #1114.