| /* |
| * 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; |
| } |