/* * Copyright (C) 2011 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "PgmImage.h" #include <cassert> using namespace std; PgmImage::PgmImage(std::string filename) : m_w(0),m_h(0),m_colors(255),m_format(PGM_BINARY_GRAYMAP),m_over_allocation(256) { if ( !ReadPGM(filename) ) return; } PgmImage::PgmImage(int w, int h, int format) : m_colors(255),m_w(w),m_h(h),m_format(format),m_over_allocation(256) { SetFormat(format); } PgmImage::PgmImage(unsigned char *data, int w, int h) : m_colors(255),m_w(w),m_h(h),m_format(PGM_BINARY_GRAYMAP),m_over_allocation(256) { SetData(data); } PgmImage::PgmImage(std::vector<unsigned char> &data, int w, int h) : m_colors(255),m_w(w),m_h(h),m_format(PGM_BINARY_GRAYMAP),m_over_allocation(256) { if ( data.size() == w*h ) SetData(&data[0]); else //throw (std::exception("Size of data is not w*h.")); throw (std::exception()); } PgmImage::PgmImage(const PgmImage &im) : m_colors(255),m_w(0),m_h(0),m_format(PGM_BINARY_GRAYMAP),m_over_allocation(256) { DeepCopy(im, *this); } PgmImage& PgmImage::operator= (const PgmImage &im) { if (this == &im) return *this; DeepCopy(im, *this); return *this; } void PgmImage::DeepCopy(const PgmImage& src, PgmImage& dst) { dst.m_data = src.m_data; // PGM data dst.m_w = src.m_w; dst.m_h = src.m_h; dst.m_format = src.m_format; dst.m_colors = src.m_colors; dst.m_comment = src.m_comment; SetupRowPointers(); } PgmImage::~PgmImage() { } void PgmImage::SetFormat(int format) { m_format = format; switch (format) { case PGM_BINARY_GRAYMAP: m_data.resize(m_w*m_h+m_over_allocation); break; case PGM_BINARY_PIXMAP: m_data.resize(m_w*m_h*3+m_over_allocation); break; default: return; break; } SetupRowPointers(); } void PgmImage::SetData(const unsigned char * data) { m_data.resize(m_w*m_h+m_over_allocation); memcpy(&m_data[0],data,m_w*m_h); SetupRowPointers(); } bool PgmImage::ReadPGM(const std::string filename) { ifstream in(filename.c_str(),std::ios::in | std::ios::binary); if ( !in.is_open() ) return false; // read the header: string format_header,size_header,colors_header; getline(in,format_header); stringstream s; s << format_header; s >> format_header >> m_w >> m_h >> m_colors; s.clear(); if ( m_w == 0 ) { while ( in.peek() == '#' ) getline(in,m_comment); getline(in,size_header); while ( in.peek() == '#' ) getline(in,m_comment); m_colors = 0; // parse header s << size_header; s >> m_w >> m_h >> m_colors; s.clear(); if ( m_colors == 0 ) { getline(in,colors_header); s << colors_header; s >> m_colors; } } if ( format_header == "P5" ) m_format = PGM_BINARY_GRAYMAP; else if (format_header == "P6" ) m_format = PGM_BINARY_PIXMAP; else m_format = PGM_FORMAT_INVALID; switch(m_format) { case(PGM_BINARY_GRAYMAP): m_data.resize(m_w*m_h+m_over_allocation); in.read((char *)(&m_data[0]),m_data.size()); break; case(PGM_BINARY_PIXMAP): m_data.resize(m_w*m_h*3+m_over_allocation); in.read((char *)(&m_data[0]),m_data.size()); break; default: return false; break; } in.close(); SetupRowPointers(); return true; } bool PgmImage::WritePGM(const std::string filename, const std::string comment) { string format_header; switch(m_format) { case PGM_BINARY_GRAYMAP: format_header = "P5\n"; break; case PGM_BINARY_PIXMAP: format_header = "P6\n"; break; default: return false; break; } ofstream out(filename.c_str(),std::ios::out |ios::binary); out << format_header << "# " << comment << '\n' << m_w << " " << m_h << '\n' << m_colors << '\n'; out.write((char *)(&m_data[0]), m_data.size()); out.close(); return true; } void PgmImage::SetupRowPointers() { int i; m_rows.resize(m_h); switch (m_format) { case PGM_BINARY_GRAYMAP: for(i=0;i<m_h;i++) { m_rows[i]=&m_data[m_w*i]; } break; case PGM_BINARY_PIXMAP: for(i=0;i<m_h;i++) { m_rows[i]=&m_data[(m_w*3)*i]; } break; } } void PgmImage::ConvertToGray() { if ( m_format != PGM_BINARY_PIXMAP ) return; // Y = 0.3*R + 0.59*G + 0.11*B; for ( int i = 0; i < m_w*m_h; ++i ) m_data[i] = (unsigned char)(0.3*m_data[3*i]+0.59*m_data[3*i+1]+0.11*m_data[3*i+2]); m_data.resize(m_w*m_h+m_over_allocation); m_format = PGM_BINARY_GRAYMAP; SetupRowPointers(); } std::ostream& operator<< (std::ostream& o, const PgmImage& im) { o << "PGM Image Info:\n"; o << "Size: " << im.m_w << " x " << im.m_h << "\n"; o << "Comment: " << im.m_comment << "\n"; switch (im.m_format) { case PgmImage::PGM_BINARY_PIXMAP: o << "Format: RGB binary pixmap"; break; case PgmImage::PGM_BINARY_GRAYMAP: o << "Format: PPM binary graymap"; break; default: o << "Format: Invalid"; break; } o << endl; return o; }