155 lines
2.5 KiB
C++
155 lines
2.5 KiB
C++
|
#include "image.h"
|
||
|
#include "pnm.h"
|
||
|
|
||
|
Image::Image()
|
||
|
: width(0)
|
||
|
, height(0)
|
||
|
, buffer(NULL)
|
||
|
, pixel_size(0)
|
||
|
{}
|
||
|
|
||
|
Image::~Image()
|
||
|
{
|
||
|
delete [] buffer;
|
||
|
}
|
||
|
|
||
|
Image::Image(unsigned int w, unsigned int h, pnm::Format type)
|
||
|
{
|
||
|
this->width = w;
|
||
|
this->height = h;
|
||
|
this->type = type;
|
||
|
|
||
|
switch (this->type)
|
||
|
{
|
||
|
case pnm::Format::PGM:
|
||
|
{
|
||
|
this->pixel_size = 1;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case pnm::Format::PPM:
|
||
|
{
|
||
|
this->pixel_size = 4;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
buffer = new pvalue_t[width * height * pixel_size];
|
||
|
memset(buffer, 0, width * height * pixel_size * sizeof (pvalue_t));
|
||
|
}
|
||
|
|
||
|
Image::Image(string const& path)
|
||
|
: Image()
|
||
|
{
|
||
|
ifstream is(path);
|
||
|
if (!is.is_open())
|
||
|
{
|
||
|
cerr << "Cannot open file '" << path << "'" << endl;
|
||
|
abort();
|
||
|
}
|
||
|
|
||
|
if (!pnm::read_header(is, this->type, this->width, this->height))
|
||
|
{
|
||
|
cerr << "Invalid header." << endl;
|
||
|
abort();
|
||
|
}
|
||
|
|
||
|
switch (this->type)
|
||
|
{
|
||
|
case pnm::Format::PGM:
|
||
|
{
|
||
|
this->pixel_size = 1;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case pnm::Format::PPM:
|
||
|
{
|
||
|
this->pixel_size = 4;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
|
||
|
if (!this->read_body(is))
|
||
|
{
|
||
|
delete buffer;
|
||
|
buffer = nullptr;
|
||
|
|
||
|
cerr << "Invalid header." << endl;
|
||
|
abort();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool Image::save(string const& path) const
|
||
|
{
|
||
|
ofstream os(path);
|
||
|
if (!os.is_open())
|
||
|
{
|
||
|
cerr << "Cannot open file '" << path << "'" << endl;
|
||
|
return false;
|
||
|
}
|
||
|
pnm::write_header(os, this->type, this->width, this->height);
|
||
|
this->write_body(os);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool Image::read_body(std::ifstream& istr)
|
||
|
{
|
||
|
unsigned int const nb_pixels = width * height;
|
||
|
buffer = new pvalue_t[nb_pixels * pixel_size];
|
||
|
|
||
|
pvalue_t* pixel = buffer;
|
||
|
for (unsigned int i = 0; i < nb_pixels; ++i)
|
||
|
{
|
||
|
switch (this->type)
|
||
|
{
|
||
|
case pnm::Format::PGM:
|
||
|
{
|
||
|
pixel[0] = istr.get();
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case pnm::Format::PPM:
|
||
|
{
|
||
|
pixel[0] = istr.get();
|
||
|
pixel[1] = istr.get();
|
||
|
pixel[2] = istr.get();
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
pixel += pixel_size;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool Image::write_body(std::ofstream& ostr) const
|
||
|
{
|
||
|
unsigned int const nb_pixels = width * height;
|
||
|
pvalue_t* pixel = buffer;
|
||
|
for (unsigned int i = 0; i < nb_pixels; ++i)
|
||
|
{
|
||
|
switch (this->type)
|
||
|
{
|
||
|
case pnm::Format::PGM:
|
||
|
{
|
||
|
ostr << (char) pixel[0];
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case pnm::Format::PPM:
|
||
|
{
|
||
|
ostr << (char) pixel[0];
|
||
|
ostr << (char) pixel[1];
|
||
|
ostr << (char) pixel[2];
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
pixel += pixel_size;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|