Bladeren bron

Merge branch 'release/v1.1.2'

Jérôme BUISINE 4 jaren geleden
bovenliggende
commit
193d9dfac4
7 gewijzigde bestanden met toevoegingen van 605 en 10 verwijderingen
  1. 4 1
      main/CMakeLists.txt
  2. 51 0
      main/rawls_update.cpp
  3. 4 0
      rawls/CMakeLists.txt
  4. 4 9
      rawls/rawls.cpp
  5. 391 0
      rawls/rawls_v1.cpp
  6. 76 0
      rawls/rawls_v1.h
  7. 75 0
      utils/update_rawls.py

+ 4 - 1
main/CMakeLists.txt

@@ -5,6 +5,7 @@ add_executable(rawls_merge_mean_incr rawls_merge_mean_incr.cpp)
 add_executable(rawls_merge_median_incr rawls_merge_median_incr.cpp)
 add_executable(rawls_merge_MON_incr rawls_merge_MON_incr.cpp)
 add_executable(rawls_merge_MON_pct_incr rawls_merge_MON_pct_incr.cpp)
+add_executable(rawls_update rawls_update.cpp)
 
 target_link_libraries(rawls_convert LINK_PUBLIC rawls)
 target_link_libraries(rawls_merge_mean LINK_PUBLIC rawls)
@@ -13,6 +14,7 @@ target_link_libraries(rawls_merge_mean_incr LINK_PUBLIC rawls)
 target_link_libraries(rawls_merge_median_incr LINK_PUBLIC rawls)
 target_link_libraries(rawls_merge_MON_incr LINK_PUBLIC rawls)
 target_link_libraries(rawls_merge_MON_pct_incr LINK_PUBLIC rawls)
+target_link_libraries(rawls_update LINK_PUBLIC rawls rawls_v1)
 
 set_property(TARGET rawls_merge_mean PROPERTY CXX_STANDARD 17)
 set_property(TARGET rawls_convert PROPERTY CXX_STANDARD 17)
@@ -20,4 +22,5 @@ set_property(TARGET rawls_h_flip PROPERTY CXX_STANDARD 17)
 set_property(TARGET rawls_merge_mean_incr PROPERTY CXX_STANDARD 17)
 set_property(TARGET rawls_merge_median_incr PROPERTY CXX_STANDARD 17)
 set_property(TARGET rawls_merge_MON_incr PROPERTY CXX_STANDARD 17)
-set_property(TARGET rawls_merge_MON_pct_incr PROPERTY CXX_STANDARD 17)
+set_property(TARGET rawls_merge_MON_pct_incr PROPERTY CXX_STANDARD 17)
+set_property(TARGET rawls_update PROPERTY CXX_STANDARD 17)

+ 51 - 0
main/rawls_update.cpp

@@ -0,0 +1,51 @@
+#include <stdio.h>
+#include <string.h>
+#include <iostream>
+#include <fstream>
+#include <vector>
+#include <tuple>
+
+#include "lodepng.h"
+#include "rawls.h"
+#include "rawls_v1.h"
+
+int main(int argc, char *argv[]){
+
+    std::string imageName;
+    std::string outfileName;
+
+    for (int i = 1; i < argc; ++i) {
+        if (!strcmp(argv[i], "--image") || !strcmp(argv[i], "-image")) {
+            imageName = argv[++i];
+        } else if (!strcmp(argv[i], "--outfile") || !strcmp(argv[i], "-outfile")) {
+            outfileName = argv[++i];
+        }
+    }
+    
+    if (!(rawls::HasExtension(imageName, ".rawls"))){
+        std::cout << "Unexpected `rawls` image name extension" << std::endl;
+        return 1;
+    }
+
+    // std::cout << "Read image `" << imageName << "` and save it into " << outfileName << " into new RAWLS format" << std::endl;
+
+    // get dimensions and data information from image
+    unsigned width, height, nbChanels;
+    float* buffer;
+
+    std::tuple<unsigned, unsigned, unsigned, float*> data = rawls_v1::getDataRAWLS(imageName);
+
+    width = std::get<0>(data);
+    height = std::get<1>(data);
+    nbChanels = std::get<2>(data);
+    buffer = std::get<3>(data);
+
+    auto comments = rawls_v1::getCommentsRAWLS(imageName);
+
+    if (!(rawls::HasExtension(outfileName, ".rawls"))){
+        std::cout << "Unexpected `rawls` image name extension" << std::endl;
+        return 1;
+    }
+
+    rawls::saveAsRAWLS(width, height, nbChanels, comments, buffer, outfileName);
+}

+ 4 - 0
rawls/CMakeLists.txt

@@ -1,6 +1,10 @@
 add_library(rawls rawls.h rawls.cpp)
+add_library(rawls_v1 rawls_v1.h rawls_v1.cpp)
 
 target_link_libraries(rawls LINK_PUBLIC lodepng)
 target_link_libraries(rawls LINK_PUBLIC stdc++fs)
 
+target_link_libraries(rawls_v1 LINK_PUBLIC lodepng)
+target_link_libraries(rawls_v1 LINK_PUBLIC stdc++fs)
+
 target_include_directories (rawls PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

+ 4 - 9
rawls/rawls.cpp

@@ -127,9 +127,7 @@ bool rawls::saveAsRAWLS(unsigned width, unsigned height, unsigned nbChanels, std
     outfile << "IHDR" << std::endl;
     outfile << ((sizeof(width) + sizeof(height) + sizeof(nbChanels)))  << std::endl;
     outfile.write((char *) &width, sizeof(width));
-    outfile << " ";
     outfile.write((char *) &height, sizeof(height));
-    outfile << " ";
     outfile.write((char *) &nbChanels, sizeof(nbChanels));
     outfile << std::endl;
 
@@ -154,8 +152,8 @@ bool rawls::saveAsRAWLS(unsigned width, unsigned height, unsigned nbChanels, std
             outfile.write((char *) &pixel[0], sizeof(pixel[0]));
             outfile.write((char *) &pixel[1], sizeof(pixel[1]));
             outfile.write((char *) &pixel[2], sizeof(pixel[2]));
-            outfile << std::endl;
         }
+        outfile << std::endl;
     }
 
     outfile.close();
@@ -165,7 +163,7 @@ bool rawls::saveAsRAWLS(unsigned width, unsigned height, unsigned nbChanels, std
         return false;
     }
 
-    std::cout << "Image is now saved as .rawls into " << outfileName << std::endl;
+    // std::cout << "Image is now saved as .rawls into " << outfileName << std::endl;
 
     return true;
 }
@@ -218,10 +216,9 @@ float* rawls::getPixelsRAWLS(std::string filename){
                 
                 buffer[nbChanels * width * y + nbChanels * x + j] = chanelValue; 
             } 
-
-            // go to next line
-            rf.get(c);
         }
+        // go to next line
+        rf.get(c);
     }
 
     rf.close();
@@ -256,9 +253,7 @@ std::tuple<unsigned, unsigned, unsigned> rawls::getDimensionsRAWLS(std::string f
             std::getline(rf, line); // avoid data size line
 
             rf.read((char *) &width, sizeof(unsigned));
-            rf.get(c);
             rf.read((char *) &height, sizeof(unsigned));
-            rf.get(c);
             rf.read((char *) &nbChanels, sizeof(unsigned));
             rf.get(c);
         }

+ 391 - 0
rawls/rawls_v1.cpp

@@ -0,0 +1,391 @@
+#include "rawls_v1.h"
+
+#include <fstream>
+#include <memory>
+#include "lodepng.h"
+
+/*
+ * Read all pixels values from .rawls image file and save as PPM image
+ */
+bool rawls_v1::convertToPPM(std::string imageName, std::string outfileName){
+
+    // get dimensions and data information from image
+    unsigned width, height, nbChanels;
+    float* buffer;
+
+    std::tuple<unsigned, unsigned, unsigned, float*> data = getDataRAWLS(imageName);
+
+    width = std::get<0>(data);
+    height = std::get<1>(data);
+    nbChanels = std::get<2>(data);
+    buffer = std::get<3>(data);
+
+    return saveAsPPM(width, height, nbChanels, buffer, outfileName);
+}
+
+/*
+ * Read all pixels values from .rawls image file and save as PNG image
+ */
+bool rawls_v1::convertToPNG(std::string imageName, std::string outfileName){
+
+    // get dimensions and data information from image
+    unsigned width, height, nbChanels;
+    float* buffer;
+
+    std::tuple<unsigned, unsigned, unsigned, float*> data = getDataRAWLS(imageName);
+
+    width = std::get<0>(data);
+    height = std::get<1>(data);
+    nbChanels = std::get<2>(data);
+    buffer = std::get<3>(data);
+
+    return saveAsPNG(width, height, nbChanels, buffer, outfileName);
+}
+
+
+/*
+ * Convert buffer using dimensions to PPM image format
+ */
+bool rawls_v1::saveAsPPM(unsigned width, unsigned height, unsigned nbChanels, float* buffer, std::string outfileName){
+
+    // open buffer
+    std::ofstream outfile(outfileName);
+
+    outfile << "P" << nbChanels << std::endl;
+    outfile << width << " " << height << std::endl;
+    outfile << "255" << std::endl;
+
+    for(unsigned y = 0; y < height; y++){
+
+        for(unsigned x = 0; x < width; x++) {
+
+            // for each chanel read and keep save float value i nto new file
+            for(int j = 0; j < nbChanels; j++){
+                outfile << int(GammaConvert(buffer[nbChanels * width * y + nbChanels * x + j])) << " "; 
+            } 
+        }
+
+        outfile << std::endl;
+    }
+
+    std::cout << "Image is now saved as .ppm into " << outfileName << std::endl;
+
+    outfile.close();
+
+    if(!outfile.good()) {
+        std::cout << "Error occurred at writing time!" << std::endl;
+        return false;
+    }
+
+    return true;
+}
+
+
+/*
+ * Convert buffer using dimensions to PNG image format
+ */
+bool rawls_v1::saveAsPNG(unsigned width, unsigned height, unsigned nbChanels, float* buffer, std::string outfileName){
+
+    // image buffer
+    unsigned nbChanelsAlpha = nbChanels + 1;
+    std::unique_ptr<uint8_t[]> outBuf(new uint8_t[width * height * nbChanelsAlpha]);
+    uint8_t *image = outBuf.get();
+
+    for(unsigned y = 0; y < height; y++){
+
+        for(unsigned x = 0; x < width; x++) {
+
+            for(int j = 0; j < nbChanels; j++){
+
+                float value = buffer[nbChanels * width * y + nbChanels * x + j];
+                image[nbChanelsAlpha * width * y + nbChanelsAlpha * x + j] = int(GammaConvert(value)); 
+            } 
+
+            // alpha channel
+            image[nbChanelsAlpha * width * y + nbChanelsAlpha * x + 3] = 255; 
+        }
+    }
+    
+    unsigned error = lodepng::encode(outfileName, image, width, height);
+   
+    //if there's an error, display it
+    if(error) {
+        std::cout << "encoder error " << error << ": "<< lodepng_error_text(error) << std::endl;
+        return false;
+    }
+
+    std::cout << "Image is now saved as .png into " << outfileName << std::endl;
+    
+    return true;
+}
+
+
+bool rawls_v1::saveAsRAWLS(unsigned width, unsigned height, unsigned nbChanels, std::string comments, float* buffer, std::string outfileName){
+    
+    std::ofstream outfile(outfileName, std::ios::out | std::ios::binary);
+
+    outfile << "IHDR" << std::endl;
+    outfile << ((sizeof(width) + sizeof(height) + sizeof(nbChanels)))  << std::endl;
+    outfile.write((char *) &width, sizeof(width));
+    outfile << " ";
+    outfile.write((char *) &height, sizeof(height));
+    outfile << " ";
+    outfile.write((char *) &nbChanels, sizeof(nbChanels));
+    outfile << std::endl;
+
+    // Part 2
+    // Comments (usefull information about scene and generation data used)
+    outfile << "COMMENTS" << std::endl;
+    outfile << comments;
+    
+    // Part 3
+    // using data information write specific chunck
+    outfile << "DATA" << std::endl;
+    outfile << (sizeof(float) * nbChanels * width * height) << std::endl;
+
+    for (int y = 0; y < height; ++y) {
+        for (int x = 0; x < width; ++x) {
+            float pixel[3];
+
+            pixel[0] = buffer[3 * (y * width + x) + 0];
+            pixel[1] = buffer[3 * (y * width + x) + 1];
+            pixel[2] = buffer[3 * (y * width + x) + 2];
+            
+            outfile.write((char *) &pixel[0], sizeof(pixel[0]));
+            outfile.write((char *) &pixel[1], sizeof(pixel[1]));
+            outfile.write((char *) &pixel[2], sizeof(pixel[2]));
+            outfile << std::endl;
+        }
+    }
+
+    outfile.close();
+    
+    if(!outfile.good()) {
+        std::cout << "Error occurred at writing time!" << std::endl;
+        return false;
+    }
+
+    // std::cout << "Image is now saved as .rawls into " << outfileName << std::endl;
+
+    return true;
+}
+
+
+float* rawls_v1::getPixelsRAWLS(std::string filename){
+
+    // get dimensions information from image
+    unsigned width, height, nbChanels;
+
+    std::tuple<unsigned, unsigned, unsigned> dimensions = getDimensionsRAWLS(filename);
+
+    width = std::get<0>(dimensions);
+    height = std::get<1>(dimensions);
+    nbChanels = std::get<2>(dimensions);
+
+    std::ifstream rf(filename, std::ios::out | std::ios::binary);
+
+    if(!rf) {
+      std::cout << "Cannot open file!" << std::endl;
+    }
+
+    std::string line; 
+    char c; // to get space of new line char
+  
+    bool dataBegin = false;
+
+    // READ DATA info
+    // case of data chunck begin
+    while (!dataBegin && std::getline(rf, line)) { 
+
+        if (line.find(std::string("DATA")) != std::string::npos){
+            dataBegin = true;
+        }
+    }
+
+    // resize buffer if necessary
+    float* buffer = new float[height * width * nbChanels];
+
+    std::getline(rf, line);
+    unsigned size = std::stoi(line);
+    float chanelValue;
+
+    for(unsigned y = 0; y < height; y++){
+
+        for(unsigned x = 0; x < width; x++) {
+
+            for(int j = 0; j < nbChanels; j++){
+                rf.read((char *) &chanelValue, sizeof(float));  
+                
+                buffer[nbChanels * width * y + nbChanels * x + j] = chanelValue; 
+            } 
+
+            // go to next line
+            rf.get(c);
+        }
+    }
+
+    rf.close();
+
+    if(!rf.good()) {
+        std::cout << "Error occurred at writing time!" << std::endl;
+    }
+
+    return buffer;
+}
+
+
+std::tuple<unsigned, unsigned, unsigned> rawls_v1::getDimensionsRAWLS(std::string filename){
+
+    std::ifstream rf(filename, std::ios::out | std::ios::binary);
+
+    if(!rf) {
+      std::cout << "Cannot open file!" << std::endl;
+    }
+
+    std::string line; 
+    unsigned nbChanels, width, height;
+    char c; // to get space of new line char
+
+    // READ IHDR info
+    bool ihdrBegin = false;
+
+    while (!ihdrBegin && std::getline(rf, line)) { 
+
+        if (line.find(std::string("IHDR")) != std::string::npos){
+            ihdrBegin = true;
+            std::getline(rf, line); // avoid data size line
+
+            rf.read((char *) &width, sizeof(unsigned));
+            rf.get(c);
+            rf.read((char *) &height, sizeof(unsigned));
+            rf.get(c);
+            rf.read((char *) &nbChanels, sizeof(unsigned));
+            rf.get(c);
+        }
+    }
+
+    rf.close();
+
+    if(!rf.good()) {
+        std::cout << "Error occurred at writing time!" << std::endl;
+    }
+
+    return std::make_tuple(width, height, nbChanels);
+}
+
+
+std::tuple<unsigned, unsigned, unsigned, float*> rawls_v1::getDataRAWLS(std::string filename){
+
+    // only one read buffer used for the whole function
+    std::ifstream rf(filename, std::ios::out | std::ios::binary);
+
+    if(!rf) {
+      std::cout << "Cannot open file!" << std::endl;
+    }
+
+    std::string line; 
+    unsigned nbChanels, width, height;
+    char c; // to get space of new line char
+
+    // READ IHDR info
+    bool ihdrBegin = false;
+
+    while (!ihdrBegin && std::getline(rf, line)) { 
+
+        if (line.find(std::string("IHDR")) != std::string::npos){
+            ihdrBegin = true;
+            std::getline(rf, line); // avoid data size line
+
+            rf.read((char *) &width, sizeof(unsigned));
+            rf.get(c);
+            rf.read((char *) &height, sizeof(unsigned));
+            rf.get(c);
+            rf.read((char *) &nbChanels, sizeof(unsigned));
+            rf.get(c);
+        }
+    }
+
+    bool dataBegin = false;
+
+    // READ DATA info
+    // case of data chunck begin
+    while (!dataBegin && std::getline(rf, line)) { 
+
+        if (line.find(std::string("DATA")) != std::string::npos){
+            dataBegin = true;
+        }
+    }
+
+    // resize buffer if necessary
+    float* buffer = new float[height * width * nbChanels];
+
+    std::getline(rf, line);
+    unsigned size = std::stoi(line);
+    float chanelValue;
+
+    for(unsigned y = 0; y < height; y++){
+
+        for(unsigned x = 0; x < width; x++) {
+
+            for(int j = 0; j < nbChanels; j++){
+                rf.read((char *) &chanelValue, sizeof(float));  
+                
+                buffer[nbChanels * width * y + nbChanels * x + j] = chanelValue; 
+            } 
+
+            // go to next line
+            rf.get(c);
+        }
+    }
+
+    rf.close();
+
+    if(!rf.good()) {
+        std::cout << "Error occurred at writing time!" << std::endl;
+    }
+
+    return std::make_tuple(width, height, nbChanels, buffer);
+}
+
+std::string rawls_v1::getCommentsRAWLS(std::string filename){
+
+    std::string comments;
+
+    // only one read buffer used for the whole function
+    std::ifstream rf(filename, std::ios::out | std::ios::binary);
+
+    if(!rf) {
+      std::cout << "Cannot open file!" << std::endl;
+    }
+
+    std::string line; 
+    unsigned nbChanels, width, height;
+    char c; // to get space of new line char
+
+    // READ IHDR info
+    bool commentsBegin = false;
+
+    while (!commentsBegin && std::getline(rf, line)) { 
+
+        if (line.find(std::string("COMMENTS")) != std::string::npos){
+            commentsBegin = true;
+        }
+    }
+
+    bool dataBegin = false;
+
+    // READ DATA info
+    // case of data chunck begin
+    while (!dataBegin && std::getline(rf, line)) { 
+
+        if (line.find(std::string("DATA")) != std::string::npos){
+            dataBegin = true;
+        }
+        else
+        {
+            comments = comments + line + '\n';
+        }
+    }
+
+    return comments;
+}

+ 76 - 0
rawls/rawls_v1.h

@@ -0,0 +1,76 @@
+#include <string.h>
+#include <iostream>
+#include <math.h>
+#include <tuple>
+
+namespace rawls_v1{
+
+/*
+ * Gamma conversion functions
+ */
+inline float GammaCorrect(float value) {
+    if (value <= 0.0031308f) return 12.92f * value;
+    return 1.055f * std::pow(value, (float)(1.f / 2.4f)) - 0.055f;
+}
+
+template <typename T, typename U, typename V>
+inline T Clamp(T val, U low, V high) {
+    if (val < low)
+        return low;
+    else if (val > high)
+        return high;
+    else
+        return val;
+}
+
+inline bool HasExtension(const std::string &value, const std::string &ending) {
+    if (ending.size() > value.size()) return false;
+    return std::equal(
+        ending.rbegin(), ending.rend(), value.rbegin(),
+        [](char a, char b) { return std::tolower(a) == std::tolower(b); });
+}
+
+//#define GAMMA_CONVERT(v) (float) rawls::Clamp(255.f * rawls::GammaCorrect(v) + 0.5f, 0.f, 255.f)
+inline float GammaConvert(float value){
+    return rawls_v1::Clamp(255.f * rawls_v1::GammaCorrect(value) + 0.5f, 0.f, 255.f);
+}
+
+
+/*
+ * Save and write functions
+ */
+bool convertToPPM(std::string imageName, std::string outfileName);
+
+bool convertToPNG(std::string imageName, std::string outfileName);
+
+bool saveAsPPM(unsigned width, unsigned height, unsigned nbChanels, float* buffer, std::string outfileName);
+
+bool saveAsPNG(unsigned width, unsigned height, unsigned nbChanels, float* buffer, std::string outfileName);
+
+bool saveAsRAWLS(unsigned width, unsigned height, unsigned nbChanels, std::string comments, float* buffer, std::string outfileName);
+
+/*
+ * Read `.rawls` image and fill buffer pass as parameter
+ *
+ * `float*` is pointer to data buffer and needed to be deleted
+ */
+float* getPixelsRAWLS(std::string filename);
+
+/*
+ * Returns comments from `.rawls` format
+ */
+std::string getCommentsRAWLS(std::string filename);
+
+/*
+ * Returns tuple with <width, height, channels> information of image
+ */
+std::tuple<unsigned, unsigned, unsigned> getDimensionsRAWLS(std::string filename);
+
+/*
+ * Returns tuple with <width, height, channels, buffer*> information of image
+ *
+ * `float*` is pointer to data buffer and needed to be deleted
+ */
+std::tuple<unsigned, unsigned, unsigned, float*> getDataRAWLS(std::string filename);
+
+};

+ 75 - 0
utils/update_rawls.py

@@ -0,0 +1,75 @@
+import os, sys
+import argparse
+import subprocess
+
+def write_progress(progress):
+    '''
+    Display progress information as progress bar
+    '''
+    barWidth = 150
+
+    output_str = "["
+    pos = barWidth * progress
+    
+    for i in range(barWidth):
+        if i < pos:
+           output_str = output_str + "="
+        elif i == pos:
+           output_str = output_str + ">"
+        else:
+            output_str = output_str + " "
+
+    output_str = output_str + "] " + str(int(progress * 100.0)) + " %\r"
+    print(output_str)
+    sys.stdout.write("\033[F")
+
+
+def main():
+
+    parser = argparse.ArgumentParser(description="Update whole scene folder .rawls files to new .rawls version format")
+
+    parser.add_argument('--folder', type=str, help='folder with all .rawls scenes sub folder', required=True)
+    parser.add_argument('--output', type=str, help='output expected folder (can be the same)', required=True)
+
+    args = parser.parse_args()
+
+    p_folder   = args.folder
+    p_output   = args.output
+
+    # check if executable file is available
+    executable_filepath = './build/main/rawls_update'
+
+    if not os.path.exists(executable_filepath):
+        print("Executable '{0}' does not exist or is not accessible as expected.".format(executable_filepath))
+
+    scenes = sorted(os.listdir(p_folder))
+
+    for scene in scenes:
+
+        scene_path = os.path.join(p_folder, scene)
+
+        # create output scene path if does not exist
+        output_scene_path = os.path.join(p_output, scene)
+
+        if not os.path.exists(output_scene_path):
+            os.makedirs(output_scene_path)
+
+        print('Convert .rawls for: {0}'.format(scene))
+
+        images = sorted(os.listdir(scene_path))
+        n_images = len(images)
+
+        for i, img in enumerate(images):
+
+            img_path = os.path.join(scene_path, img)
+            out_img_path = os.path.join(output_scene_path, img)
+
+            # create and launch command
+            subprocess.call([executable_filepath, '--image', img_path, '--outfile', out_img_path])
+
+            write_progress((i + 1 ) / float(n_images))
+
+        print('\n')
+
+if __name__ == "__main__":
+    main()