123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391 |
- #include "rawls.h"
- #include <fstream>
- #include <memory>
- #include "lodepng.h"
- /*
- * Read all pixels values from .rawls image file and save as PPM image
- */
- bool rawls::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::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::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::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));
- }
- 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::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::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::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::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::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;
- }
|