Line data Source code
1 0 : #include <cstdio> 2 : #include <cstdlib> 3 : #include <ctime> 4 : #include <vector> 5 : 6 : extern "C" { 7 : int SaveEXRSnapshot(const char* outfilename, int width, int height, const float* rgb); 8 : } 9 : 10 : #ifdef WIN32 11 : #define TINYEXR_IMPLEMENTATION 12 : #include "tinyexr.h" 13 : 14 : int SaveEXRSnapshot(const char* outfilename, int width, int height, const float* rgb) 15 : { 16 : EXRHeader header; 17 : InitEXRHeader(&header); 18 : 19 : EXRImage image; 20 : InitEXRImage(&image); 21 : 22 : image.num_channels = 3; 23 : 24 : std::vector<float> images[3]; 25 : images[0].resize(width * height); 26 : images[1].resize(width * height); 27 : images[2].resize(width * height); 28 : 29 : for (int i = 0; i < width * height; i++) 30 : { 31 : images[0][i] = rgb[3*i+0]; 32 : images[1][i] = rgb[3*i+1]; 33 : images[2][i] = rgb[3*i+2]; 34 : } 35 : 36 : float* image_ptr[3]; 37 : image_ptr[0] = &(images[2].at(0)); // B 38 : image_ptr[1] = &(images[1].at(0)); // G 39 : image_ptr[2] = &(images[0].at(0)); // R 40 : 41 : image.images = (unsigned char**)image_ptr; 42 : image.width = width; 43 : image.height = height; 44 : 45 : header.num_channels = 3; 46 : header.compression_type = TINYEXR_COMPRESSIONTYPE_ZIP; 47 : header.channels = (EXRChannelInfo *)malloc(sizeof(EXRChannelInfo) * header.num_channels); 48 : 49 : // sign our snapshot 50 : header.num_custom_attributes = 1; 51 : header.custom_attributes = static_cast<EXRAttribute *>(malloc(sizeof(EXRAttribute))); 52 : strncpy(header.custom_attributes[0].name, "signature", 255); 53 : strncpy(header.custom_attributes[0].type, "string", 255); 54 : std::time_t timestamp; 55 : std::time(×tamp); 56 : char signatureStringIntro[255] = "Generated by Oolite "; 57 : char *signatureString = strcat(signatureStringIntro, std::ctime(×tamp)); 58 : // ctime adds a newline at the end of the string, strip it 59 : signatureString[strlen(signatureString) - 1] = '\0'; 60 : header.custom_attributes[0].value = reinterpret_cast<uint8_t *>(signatureString); 61 : header.custom_attributes[0].size = strlen(signatureString); 62 : 63 : // Must be BGR(A) order, since most of EXR viewers expect this channel order. 64 : strncpy(header.channels[0].name, "B", 255); header.channels[0].name[strlen("B")] = '\0'; 65 : strncpy(header.channels[1].name, "G", 255); header.channels[1].name[strlen("G")] = '\0'; 66 : strncpy(header.channels[2].name, "R", 255); header.channels[2].name[strlen("R")] = '\0'; 67 : 68 : header.pixel_types = (int *)malloc(sizeof(int) * header.num_channels); 69 : header.requested_pixel_types = (int *)malloc(sizeof(int) * header.num_channels); 70 : for (int i = 0; i < header.num_channels; i++) 71 : { 72 : header.pixel_types[i] = TINYEXR_PIXELTYPE_FLOAT; // pixel type of input image 73 : header.requested_pixel_types[i] = TINYEXR_PIXELTYPE_HALF; // pixel type of output image to be stored in .EXR 74 : } 75 : 76 : const char* err; 77 : int ret = SaveEXRImageToFile(&image, &header, outfilename, &err); 78 : if (ret != TINYEXR_SUCCESS) 79 : { 80 : fprintf(stderr, "Save EXR err: %s\n", err); 81 : } 82 : 83 : free(header.channels); 84 : free(header.pixel_types); 85 : free(header.requested_pixel_types); 86 : 87 : return ret; 88 : } 89 : #else // Linux EXR snaphsots not supported yet 90 0 : int SaveEXRSnapshot(const char* outfilename, int width, int height, const float* rgb) 91 : { 92 : fprintf(stderr, "EXR Snapshot not supported yet under Linux!\n"); 93 : return 0; 94 : } 95 : #endif