// K-3D
// Copyright (c) 1995-2004, Timothy M. Shead
//
// Contact: tshead@k-3d.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 2 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, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

/** \file
		\brief Implements the TIFF writer K-3D object, which writes bitmap images using Sam Leffler's libtiff API
		\author Timothy M. Shead
*/

#include <k3dsdk/ibitmap_write_format.h>
#include <k3dsdk/ideletable.h>
#include <k3dsdk/ifile_format.h>
#include <k3dsdk/classes.h>
#include <k3dsdk/module.h>
#include <k3dsdk/string_modifiers.h>

#include <tiffio.h>

namespace
{

/////////////////////////////////////////////////////////////////////////////
// tiff_writer_implementation

class tiff_writer_implementation :
	public k3d::ifile_format,
	public k3d::ibitmap_write_format,
	public k3d::ideletable
{
public:
	tiff_writer_implementation()
	{
	}

	unsigned long priority()
	{
		return 10;
	}

	bool query_can_handle(const boost::filesystem::path& File)
	{
		return_val_if_fail(!File.empty(), false);
		return "tiff" == k3d::file_extension(File) ||
			"tif" == k3d::file_extension(File);
	}

	bool write_file(const boost::filesystem::path& File, const k3d::bitmap& Bitmap)
	{
		// Sanity checks ...
		return_val_if_fail(!File.empty(), false);

		std::cerr << info << "Write " << File.native_file_string() << " using TIFFWriter" << std::endl;

		// Convert the input bitmap to 8-bit-integer samples (would prefer to store images as floating-point, but we have to establish the lowest common denominator of what various render engines will read)
		typedef k3d::basic_rgba<boost::uint8_t> integer_pixel_t;
		typedef k3d::basic_bitmap<integer_pixel_t> integer_bitmap_t;
		integer_bitmap_t bitmap(Bitmap);

		//start getting the bitmap data out
		const integer_pixel_t* data = bitmap.data();
		const k3d::pixel_size_t width = bitmap.width();
		const k3d::pixel_size_t height = bitmap.height();

		TIFF* const file = TIFFOpen(File.native_file_string().c_str(), "w");
		if(!file)
			{
				std::cerr << error << "Error opening [" << File.native_file_string() << "] for TIFF output" << std::endl;
				return false;
			}

		TIFFSetField(file, TIFFTAG_IMAGEWIDTH, width);
		TIFFSetField(file, TIFFTAG_IMAGELENGTH, height);
		TIFFSetField(file, TIFFTAG_BITSPERSAMPLE, 8);
		TIFFSetField(file, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
		TIFFSetField(file, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
		TIFFSetField(file, TIFFTAG_SAMPLESPERPIXEL, 4);
		TIFFSetField(file, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
		TIFFSetField(file, TIFFTAG_ROWSPERSTRIP, 1);
		TIFFSetField(file, TIFFTAG_IMAGEDESCRIPTION, "Created with K-3D, http://www.k-3d.org");

		for(k3d::pixel_size_t row = 0; row != height; ++row)
			{
				if(TIFFWriteScanline(file, const_cast<integer_pixel_t*>(data), row, 0) < 0)
					{
						TIFFClose(file);
						std::cerr << error << "Error writing data to [" << File.native_file_string() << "] for TIFF output" << std::endl;
						return false;
					}
				data += width;
			}
		
		TIFFClose(file);

		return true;

	}

	k3d::iplugin_factory& factory()
	{
		return get_factory();
	}

	static k3d::iplugin_factory& get_factory()
	{
		static k3d::plugin_factory<
			k3d::application_plugin<tiff_writer_implementation>,
			k3d::interface_list<k3d::ibitmap_write_format> > factory(
			k3d::classes::TIFFWriter(),
			"TIFFWriter",
			"TIFF (*.tiff)",
			"Bitmap File Formats");

		return factory;
	}

private:

};
}//namespace

/////////////////////////////////////////////////////////////////////////////
// Helper functions

namespace libk3dtiff
{

/////////////////////////////////////////////////////////////////////////////
// tiff_writer_factory

k3d::iplugin_factory& tiff_writer_factory()
{
	return ::tiff_writer_implementation::get_factory();
}

} // namespace libk3dtiff


