message: flip buffers for EXR exporting
diff: @@ -29,6 +29,7 @@ namespace ospray::sg {
  ~EXRExporter() = default;
  void doExport() override;
  + float *flipBuffer(const void *buf, int ncomp=4);
  };
  OSP_REGISTER_SG_NODE_NAME(EXRExporter, exporter_exr);
  @@ -66,23 +67,30 @@ namespace ospray::sg {
  exrHeader.channels().insert("A", Imf::Channel(IMF::FLOAT));
  auto makeSlice = [&](const void *fb, int offset, int ncomp = 4) {
  + // flip the data
  return Imf::Slice(IMF::FLOAT,
  (char *)((float *)fb + offset),
  sizeof(float) * ncomp,
  size.x * sizeof(float) * ncomp);
  };
  + // although openexr provides a LineOrder parameter, it doesn't seem to
  + // actually flip the image...
  + float *flippedfb = flipBuffer(fb);
  + float *flippedz = nullptr;
  +
  Imf::FrameBuffer exrFb;
  // generic API requires channels individually
  - exrFb.insert("R", makeSlice(fb, 0));
  - exrFb.insert("G", makeSlice(fb, 1));
  - exrFb.insert("B", makeSlice(fb, 2));
  - exrFb.insert("A", makeSlice(fb, 3));
  + exrFb.insert("R", makeSlice(flippedfb, 0));
  + exrFb.insert("G", makeSlice(flippedfb, 1));
  + exrFb.insert("B", makeSlice(flippedfb, 2));
  + exrFb.insert("A", makeSlice(flippedfb, 3));
  if (hasChild("depth")) {
  exrHeader.channels().insert("Z", Imf::Channel(IMF::FLOAT));
  const void *depth = child("depth").valueAs<const void *>();
  - exrFb.insert("Z", makeSlice(depth, 0, 1));
  + flippedz = flipBuffer(depth, 1);
  + exrFb.insert("Z", makeSlice(flippedz, 0, 1));
  }
  Imf::OutputFile exrFile(file.c_str(), exrHeader);
  @@ -90,6 +98,27 @@ namespace ospray::sg {
  exrFile.writePixels(size.y);
  std::cout << "Saved to " << file << std::endl;
  +
  + free(flippedfb);
  + if (flippedz != nullptr)
  + free(flippedz);
  + }
  +
  + float *EXRExporter::flipBuffer(const void *buf, int ncomp)
  + {
  + vec2i size = child("size").valueAs<vec2i>();
  + float *flipped =
  + (float *)std::malloc(size.x * size.y * ncomp * sizeof(float));
  +
  + for (int y = size.y - 1; y >= 0; y--) {
  + size_t irow = y * size.x * ncomp;
  + size_t orow = (size.y - 1 - y) * size.x * ncomp;
  + std::memcpy(flipped + orow,
  + ((float *)buf) + irow,
  + size.x * ncomp * sizeof(float));
  + }
  +
  + return flipped;
  }
  } // namespace ospray::sg
  