#ifndef PNM_H #define PNM_H /* 3dv-client/pnm.h * * Copyright (C) 2013 VisLab * * This file is part of 3dv-client; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or (at * your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, see . */ #ifdef _MSC_VER #include #else #include #endif #include #include #include #include #include #ifdef ARCHIVE #include template size_t ppm_file_size(unsigned int width, unsigned int height, const std::string& comment = std::string(), T max_value = std::numeric_limits::max()) { size_t size = 3 + 1 + comment.size() + 1; std::stringstream ss; ss << width << ' ' << height << '\n' << static_cast(max_value) << '\n'; size += ss.str().size(); // header size += width * height * 3 * sizeof(T); return size; } template size_t pgm_file_size(unsigned int width, unsigned int height, const std::string& comment = std::string(), T max_value = std::numeric_limits::max()) { size_t size = 3 + 1 + comment.size() + 1; std::stringstream ss; ss << width << ' ' << height << '\n' << static_cast(max_value) << '\n'; size += ss.str().size(); // header size += width * height * sizeof(T); return size; } /** * Writes a PPM file of up to 16 bits per pixel. * @param archive the archive to write to * @param buffer an RGB buffer (3 channels). * @param width the number of image columns. * @param height the number of image rows. * @param comment a comment to embed into the file. Defaults to std::string(). * @param max_value the maximum pixel value contained within the image. Defaults to std::numeric_limits::max(). * @return true if the file could be written successfully, false otherwise. */ template bool write_ppm(archive* archive, const T* buffer, unsigned int width, unsigned int height, const std::string& comment = std::string(), T max_value = std::numeric_limits::max()) { if(sizeof(T) > 2) return false; archive_write_data(archive, "P6\n", 3); if(!comment.empty()) { archive_write_data(archive, "#", 1); archive_write_data(archive, comment.c_str(), comment.size()); archive_write_data(archive, "\n", 1); } std::stringstream ss; ss << width << ' ' << height << '\n' << static_cast(max_value) << '\n'; archive_write_data(archive, ss.str().c_str(), ss.str().size()); if(sizeof(T) == 2) { for(unsigned int p = 0; p < width * height * 3; ++p) { uint16_t pixel_big_endian = htons(buffer[p]); archive_write_data(archive, reinterpret_cast(&pixel_big_endian), sizeof(pixel_big_endian)); } } else archive_write_data(archive, reinterpret_cast(buffer), width * height * 3); return true; } /** * Writes a PGM file of up to 16 bits per pixel. * @param archive the archive to write to * @param buffer a grayscale buffer (1 channel). * @param width the number of image columns. * @param height the number of image rows. * @param comment a comment to embed into the file. Defaults to std::string() * @param max_value the maximum pixel value contained within the image. Defaults to std::numeric_limits::max(). * @return true if the file could be written successfully, false otherwise. */ template bool write_pgm(archive* archive, const T* buffer, unsigned int width, unsigned int height, const std::string& comment = std::string(), T max_value = std::numeric_limits::max()) { if(sizeof(T) > 2) return false; archive_write_data(archive, "P5\n", 3); if(!comment.empty()) { archive_write_data(archive, "#", 1); archive_write_data(archive, comment.c_str(), comment.size()); archive_write_data(archive, "\n", 1); } std::stringstream ss; ss << width << ' ' << height << '\n' << static_cast(max_value) << '\n'; archive_write_data(archive, ss.str().c_str(), ss.str().size()); if(sizeof(T) > 1) { for(unsigned int p = 0; p < width * height; ++p) { uint16_t pixel_big_endian = htons(buffer[p]); archive_write_data(archive, reinterpret_cast(&pixel_big_endian), sizeof(pixel_big_endian)); } } else archive_write_data(archive, reinterpret_cast(buffer), width * height); return true; } #endif /** * Writes a PPM file of up to 16 bits per pixel. * @param filename the name of the file to write to * @param buffer an RGB buffer (3 channels). * @param width the number of image columns. * @param height the number of image rows. * @param comment a comment to embed into the file. Defaults to std::string(). * @param max_value the maximum pixel value contained within the image. Defaults to std::numeric_limits::max(). * @return true if the file could be written successfully, false otherwise. */ template bool write_ppm(const std::string& filename, const T* buffer, unsigned int width, unsigned int height, const std::string& comment = std::string(), T max_value = std::numeric_limits::max()) { if(sizeof(T) > 2) return false; std::ofstream file(filename.c_str(), std::ios::out | std::ios::binary); if(file) { std::stringstream ss; ss << static_cast(max_value); file << "P6\n"; if(!comment.empty()) file << '#' << comment << '\n'; file << width << ' ' << height << '\n' << ss.str() << '\n'; if(sizeof(T) == 2) { for(unsigned int p = 0; p < width * height * 3; ++p) { uint16_t pixel_big_endian = htons(buffer[p]); file.write(reinterpret_cast(&pixel_big_endian), sizeof(pixel_big_endian)); } } else file.write(reinterpret_cast(buffer), width * height * 3); return true; } return false; } /** * Writes a PGM file of up to 16 bits per pixel. * @param filename the name of the file to write to. * @param buffer a grayscale buffer (1 channel). * @param width the number of image columns. * @param height the number of image rows. * @param comment a comment to embed into the file. Defaults to std::string() * @param max_value the maximum pixel value contained within the image. Defaults to std::numeric_limits::max(). * @return true if the file could be written successfully, false otherwise. */ template bool write_pgm(const std::string& filename, const T* buffer, unsigned int width, unsigned int height, const std::string& comment = std::string(), T max_value = std::numeric_limits::max()) { if(sizeof(T) > 2) return false; std::ofstream file(filename.c_str(), std::ios::out | std::ios::binary); if(file) { std::stringstream ss; ss << static_cast(max_value); file << "P5\n"; if(!comment.empty()) file << '#' << comment << '\n'; file << width << ' ' << height << "\n" << ss.str() << "\n"; if(sizeof(T) > 1) { for(unsigned int p = 0; p < width * height; ++p) { uint16_t pixel_big_endian = htons(buffer[p]); file.write(reinterpret_cast(&pixel_big_endian), sizeof(pixel_big_endian)); } } else file.write(reinterpret_cast(buffer), width * height); return true; } return false; } static void pnm_read_time(std::istream & i,boost::posix_time::ptime & timestamp) { std::string date; std::string time; while (isspace(i.peek())) { while (isspace(i.peek())) i.get(); if (i.peek() == '#') { i.get(); i>>date; i>>time; timestamp = boost::posix_time::time_from_string(date+" "+time); } } } static void pnm_read_comments(std::istream & i) { std::string date; std::string time; while (isspace(i.peek())) { while (isspace(i.peek())) i.get(); if (i.peek() == '#') while (i.peek()!='\r' && i.peek()!='\n') i.get(); } } static char pnm_read_header(uint16_t & width, uint16_t &height, std::istream &iss,boost::posix_time::ptime & timestamp) { char h, t; int max_val; h = iss.get(); t = iss.get(); if(!((h=='P') && ((t=='5') || (t=='6')))) { return '\0'; } pnm_read_time(iss,timestamp); iss>>width; pnm_read_comments(iss); iss>>height; pnm_read_comments(iss); iss>>max_val; iss.get(); return t; } template bool pnm_load(boost::shared_ptr & output_image, const char *file,lib3dv::image::type::types type) { std::ifstream istr(file, std::ios::binary); T *buffer = NULL; uint16_t width; uint16_t height; char c = pnm_read_header(width,height,istr,output_image->m_timestamp); if(c=='5') { output_image->m_channels=1; buffer = new T [width * height]; istr.read(reinterpret_cast(buffer), width * height*sizeof(T)); } else if(c=='6') { output_image->m_channels=3; buffer = new T [width * height*3]; istr.read(reinterpret_cast(buffer), width * height*3); } else return false; output_image->m_height=height; output_image->m_width=width; output_image->m_bpp = 8*sizeof(T); output_image->m_type = type; output_image->m_format = (lib3dv::image::format::types)(output_image->m_channels*sizeof(T)); output_image->m_buffer.resize(width*height*output_image->m_channels*sizeof(T)); if(type==lib3dv::image::type::DSI) { int k=0; for(int i=0;im_width*output_image->m_height;i++) { output_image->m_buffer[k++]=((uint8_t)((buffer[i] & 0xFF00) >> 8)); output_image->m_buffer[k++]=((uint8_t)(buffer[i] & 0x00FF)); } } else memcpy(&(output_image->m_buffer[0]),buffer,output_image->m_width*output_image->m_height*output_image->m_channels); free(buffer); return true; } #endif