/*
    Scan Tailor - Interactive post-processing tool for scanned pages.
    Copyright (C) 2007-2015  Joseph Artsimovich <joseph.artsimovich@gmail.com>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU 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 General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef IMAGEPROC_REDUCETHRESHOLD_H_
#define IMAGEPROC_REDUCETHRESHOLD_H_

#include "imageproc_config.h"
#include "BinaryImage.h"

namespace imageproc
{

/**
 * \brief Performs 2x horizontal and vertical downscaling on 1-bit images.
 *
 * The dimensions of the target image will be:
 * \code
 * dst_width = max(1, floor(src_width / 2));
 * dst_height = max(1, floor(src_height / 2));
 * \endcode
 * \n
 * Processing a null image results in a null image.
 * Processing a non-null image never results in a null image.\n
 * \n
 * A 2x2 square in the source image becomes 1 pixel in the target image.
 * The threshold parameter controls how many black pixels need to be in
 * the source 2x2 square in order to make the destination pixel black.
 * Valid threshold values are 1, 2, 3 and 4.\n
 * \n
 * If the source image is a line 1 pixel thick, downscaling will be done
 * as if the line was thickened to 2 pixels by duplicating existing pixels.\n
 * \n
 * It is possible to do a cascade of reductions:
 * \code
 * BinaryImage out = ReduceThreshold(input)(4)(4)(3);
 * \endcode
 */
class IMAGEPROC_EXPORT ReduceThreshold
{
public:
	/**
	 * \brief Constructor.  Doesn't do any work by itself.
	 */
	ReduceThreshold(BinaryImage const& image);
	
	/**
	 * \brief Implicit conversion to BinaryImage.
	 */
	operator BinaryImage const&() const { return m_image; }
	
	/**
	 * \brief Returns a reference to the reduced image.
	 */
	BinaryImage const& image() const { return m_image; }
	
	/**
	 * \brief Performs a reduction and returns *this.
	 */
	ReduceThreshold& reduce(int threshold);
	
	/**
	 * \brief Operator () performs a reduction and returns *this.
	 */
	ReduceThreshold& operator()(int threshold) {
		return reduce(threshold);
	}
private:
	void reduceHorLine(int threshold);
	
	void reduceVertLine(int threshold);
	
	/**
	 * \brief The result of a previous reduction.
	 */
	BinaryImage m_image;
};


} // namespace imageproc

#endif
