#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