Toshihiro Shimizu 890ddd
#if _MSC_VER >= 1400
Toshihiro Shimizu 890ddd
#define _CRT_SECURE_NO_DEPRECATE 1
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Shinya Kitaoka 79e39b
#include <memory></memory>
Shinya Kitaoka 79e39b
Toshihiro Shimizu 890ddd
#include "tmachine.h"
Toshihiro Shimizu 890ddd
#include "texception.h"
Toshihiro Shimizu 890ddd
#include "tfilepath.h"
Toshihiro Shimizu 890ddd
#include "tiio_png.h"
Toshihiro Shimizu 890ddd
#include "tiio.h"
Toshihiro Shimizu 890ddd
#include "../compatibility/tfile_io.h"
Toshihiro Shimizu 890ddd
fukasawa e60969
#include "png.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tpixel.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
using namespace std;
Toshihiro Shimizu 890ddd
//------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
extern "C" {
fukasawa 13abb6
fukasawa 13abb6
void tnz_abort(jmp_buf, int)
fukasawa 13abb6
{
fukasawa 13abb6
}
fukasawa 13abb6
Toshihiro Shimizu 890ddd
void tnz_error_fun(png_structp pngPtr, png_const_charp error_message)
Toshihiro Shimizu 890ddd
{
fukasawa e60969
	*(int*)png_get_error_ptr(pngPtr) = 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#if !defined(TNZ_LITTLE_ENDIAN)
Toshihiro Shimizu 890ddd
TNZ_LITTLE_ENDIAN undefined !!
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
fukasawa 13abb6
//=========================================================
Toshihiro Shimizu 890ddd
fukasawa 13abb6
inline USHORT mySwap(USHORT val)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
#if TNZ_LITTLE_ENDIAN
Toshihiro Shimizu 890ddd
	return ((val) | ((val & 0xff) << 8)); //((val>>8)|((val&0xff)<<8)); (vecchio codice)
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
	return val;
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=========================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class PngReader : public Tiio::Reader
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	FILE *m_chan;
Toshihiro Shimizu 890ddd
	png_structp m_png_ptr;
Toshihiro Shimizu 890ddd
	png_infop m_info_ptr, m_end_info_ptr;
Toshihiro Shimizu 890ddd
	int m_bit_depth, m_color_type, m_interlace_type;
Toshihiro Shimizu 890ddd
	int m_compression_type, m_filter_type;
Toshihiro Shimizu 890ddd
	unsigned int m_sig_read;
Toshihiro Shimizu 890ddd
	int m_y;
Toshihiro Shimizu 890ddd
	bool m_is16bitEnabled;
Shinya Kitaoka 79e39b
	std::unique_ptr<unsigned char[]=""> m_rowBuffer;</unsigned>
Shinya Kitaoka 79e39b
	std::unique_ptr<unsigned char[]=""> m_tempBuffer; //Buffer temporaneo</unsigned>
fukasawa e60969
	int m_canDelete;
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	PngReader()
Shinya Kitaoka 79e39b
		: m_chan(0)
Shinya Kitaoka 79e39b
		, m_png_ptr(0)
Shinya Kitaoka 79e39b
		, m_info_ptr(0)
Shinya Kitaoka 79e39b
		, m_end_info_ptr(0)
Shinya Kitaoka 79e39b
		, m_bit_depth(0)
Shinya Kitaoka 79e39b
		, m_color_type(0)
Shinya Kitaoka 79e39b
		, m_interlace_type(0)
Shinya Kitaoka 79e39b
		, m_compression_type(0)
Shinya Kitaoka 79e39b
		, m_filter_type(0)
Shinya Kitaoka 79e39b
		, m_sig_read(0)
Shinya Kitaoka 79e39b
		, m_y(0)
Shinya Kitaoka 79e39b
		, m_is16bitEnabled(true)
Shinya Kitaoka 79e39b
		, m_canDelete(0)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	~PngReader()
Toshihiro Shimizu 890ddd
	{
fukasawa e60969
		if (m_canDelete == 1) {
fukasawa 13abb6
			png_destroy_read_struct(&m_png_ptr, &m_info_ptr, &m_end_info_ptr);
fukasawa 13abb6
		}
Toshihiro Shimizu 890ddd
	}
fukasawa 13abb6
	
Toshihiro Shimizu 890ddd
	virtual bool read16BitIsEnabled() const { return m_is16bitEnabled; }
Toshihiro Shimizu 890ddd
	virtual void enable16BitRead(bool enabled) { m_is16bitEnabled = enabled; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void readLineInterlace(char *buffer) { readLineInterlace(buffer, 0, m_info.m_lx - 1, 1); }
Toshihiro Shimizu 890ddd
	void readLineInterlace(short *buffer) { readLineInterlace(buffer, 0, m_info.m_lx - 1, 1); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void open(FILE *file)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		try {
Toshihiro Shimizu 890ddd
			m_chan = file;
Toshihiro Shimizu 890ddd
		} catch (...) {
Toshihiro Shimizu 890ddd
			perror("uffa");
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		unsigned char signature[8]; // da 1 a 8 bytes
Toshihiro Shimizu 890ddd
		fread(signature, 1, sizeof signature, m_chan);
Toshihiro Shimizu 890ddd
		bool isPng = !png_sig_cmp(signature, 0, sizeof signature);
Toshihiro Shimizu 890ddd
		if (!isPng)
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_png_ptr = png_create_read_struct(
fukasawa e60969
			PNG_LIBPNG_VER_STRING, &m_canDelete, tnz_error_fun, 0);
Toshihiro Shimizu 890ddd
		if (!m_png_ptr)
Toshihiro Shimizu 890ddd
			return;
fukasawa 13abb6
fukasawa 13abb6
		png_set_longjmp_fn(m_png_ptr, tnz_abort, sizeof(jmp_buf)); /* ignore all fatal errors */
fukasawa 13abb6
fukasawa 13abb6
		m_canDelete = 1;
Toshihiro Shimizu 890ddd
		m_info_ptr = png_create_info_struct(m_png_ptr);
Toshihiro Shimizu 890ddd
		if (!m_info_ptr) {
Toshihiro Shimizu 890ddd
			png_destroy_read_struct(&m_png_ptr,
Toshihiro Shimizu 890ddd
									(png_infopp)0, (png_infopp)0);
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		m_end_info_ptr = png_create_info_struct(m_png_ptr);
Toshihiro Shimizu 890ddd
		if (!m_end_info_ptr) {
Toshihiro Shimizu 890ddd
			png_destroy_read_struct(&m_png_ptr,
Toshihiro Shimizu 890ddd
									&m_info_ptr, (png_infopp)0);
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		png_init_io(m_png_ptr, m_chan);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		png_set_sig_bytes(m_png_ptr, sizeof signature);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#if defined(TNZ_MACHINE_CHANNEL_ORDER_MBGR)
Toshihiro Shimizu 890ddd
		png_set_bgr(m_png_ptr);
Toshihiro Shimizu 890ddd
		png_set_swap_alpha(m_png_ptr);
Toshihiro Shimizu 890ddd
#elif defined(TNZ_MACHINE_CHANNEL_ORDER_BGRM)
Toshihiro Shimizu 890ddd
		png_set_bgr(m_png_ptr);
Toshihiro Shimizu 890ddd
#elif defined(TNZ_MACHINE_CHANNEL_ORDER_MRGB)
Toshihiro Shimizu 890ddd
		png_set_swap_alpha(m_png_ptr);
Toshihiro Shimizu 890ddd
#elif !defined(TNZ_MACHINE_CHANNEL_ORDER_RGBM)
Campbell Barton 42d601
#error	"unknown channel order"
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		png_read_info(m_png_ptr, m_info_ptr);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (png_get_valid(m_png_ptr, m_info_ptr, PNG_INFO_pHYs)) {
Toshihiro Shimizu 890ddd
			png_uint_32 xdpi = png_get_x_pixels_per_meter(m_png_ptr, m_info_ptr);
Toshihiro Shimizu 890ddd
			png_uint_32 ydpi = png_get_y_pixels_per_meter(m_png_ptr, m_info_ptr);
Toshihiro Shimizu 890ddd
			m_info.m_dpix = tround(xdpi * 0.0254);
Toshihiro Shimizu 890ddd
			m_info.m_dpiy = tround(ydpi * 0.0254);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		int rowBytes = png_get_rowbytes(m_png_ptr, m_info_ptr);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TUINT32 lx = 0, ly = 0;
Toshihiro Shimizu 890ddd
		png_get_IHDR(m_png_ptr, m_info_ptr, &lx, &ly, &m_bit_depth, &m_color_type,
Toshihiro Shimizu 890ddd
					 &m_interlace_type, &m_compression_type, &m_filter_type);
Toshihiro Shimizu 890ddd
		m_info.m_lx = lx;
Toshihiro Shimizu 890ddd
		m_info.m_ly = ly;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_info.m_bitsPerSample = m_bit_depth;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		int channels = png_get_channels(m_png_ptr, m_info_ptr);
Toshihiro Shimizu 890ddd
		m_info.m_samplePerPixel = channels;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (channels == 1 || channels == 2) {
Toshihiro Shimizu 890ddd
			if (m_bit_depth < 8) // (m_bit_depth == 1 || m_bit_depth == 2 || m_bit_depth == 4)
Shinya Kitaoka 79e39b
				m_rowBuffer.reset(new unsigned char[lx * 3]);
Toshihiro Shimizu 890ddd
			else
Shinya Kitaoka 79e39b
				m_rowBuffer.reset(new unsigned char[rowBytes * 4]);
Toshihiro Shimizu 890ddd
		} else {
Shinya Kitaoka 79e39b
			m_rowBuffer.reset(new unsigned char[rowBytes]);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (m_color_type == PNG_COLOR_TYPE_PALETTE) {
Toshihiro Shimizu 890ddd
			m_info.m_valid = true;
Toshihiro Shimizu 890ddd
			png_set_palette_to_rgb(m_png_ptr);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (m_color_type == PNG_COLOR_TYPE_GRAY &&
fukasawa 13abb6
			m_bit_depth < 8) {
fukasawa e60969
			png_set_expand_gray_1_2_4_to_8(m_png_ptr);
fukasawa 13abb6
		}
Toshihiro Shimizu 890ddd
fukasawa 13abb6
		if (png_get_valid(m_png_ptr, m_info_ptr, PNG_INFO_tRNS)) {
Toshihiro Shimizu 890ddd
			png_set_tRNS_to_alpha(m_png_ptr);
fukasawa 13abb6
		}
Toshihiro Shimizu 890ddd
fukasawa 13abb6
		if (m_bit_depth == 16 && !m_is16bitEnabled) {
Toshihiro Shimizu 890ddd
			png_set_strip_16(m_png_ptr);
fukasawa 13abb6
		}
fukasawa 13abb6
	   
Toshihiro Shimizu 890ddd
#if defined(TNZ_MACHINE_CHANNEL_ORDER_BGRM)
Toshihiro Shimizu 890ddd
		if (m_color_type == PNG_COLOR_TYPE_RGB ||
fukasawa 13abb6
			m_color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
Toshihiro Shimizu 890ddd
			png_set_bgr(m_png_ptr);
fukasawa 13abb6
		}
Toshihiro Shimizu 890ddd
#elif defined(TNZ_MACHINE_CHANNEL_ORDER_MBGR)
fukasawa 13abb6
		if (m_color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
Toshihiro Shimizu 890ddd
			png_set_swap_alpha(m_png_ptr);
fukasawa 13abb6
		}
Toshihiro Shimizu 890ddd
#elif !defined(TNZ_MACHINE_CHANNEL_ORDER_RGBM) && !defined(TNZ_MACHINE_CHANNEL_ORDER_MRGB)
Campbell Barton 42d601
#error	"unknown channel order"
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (m_color_type == PNG_COLOR_TYPE_GRAY ||
fukasawa 13abb6
			m_color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
Toshihiro Shimizu 890ddd
			png_set_gray_to_rgb(m_png_ptr);
fukasawa 13abb6
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void readLine(char *buffer, int x0, int x1, int shrink)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		int ly = m_info.m_ly;
Toshihiro Shimizu 890ddd
		if (!m_tempBuffer) {
Toshihiro Shimizu 890ddd
			int lx = m_info.m_lx;
Toshihiro Shimizu 890ddd
			int channels = png_get_channels(m_png_ptr, m_info_ptr);
Toshihiro Shimizu 890ddd
			int rowBytes = png_get_rowbytes(m_png_ptr, m_info_ptr);
Toshihiro Shimizu 890ddd
			if (m_interlace_type == 1) {
Toshihiro Shimizu 890ddd
				if (channels == 1 || channels == 2) {
Toshihiro Shimizu 890ddd
					if (m_bit_depth < 8)
Shinya Kitaoka 79e39b
						m_tempBuffer.reset(new unsigned char[ly * lx * 3]);
Toshihiro Shimizu 890ddd
					else
Shinya Kitaoka 79e39b
						m_tempBuffer.reset(new unsigned char[ly * rowBytes * 4]);
Toshihiro Shimizu 890ddd
				} else {
Shinya Kitaoka 79e39b
					m_tempBuffer.reset(new unsigned char[ly * rowBytes]);
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		int lx = m_info.m_lx;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (m_interlace_type == 1 && lx > 4) {
Toshihiro Shimizu 890ddd
			readLineInterlace(&buffer[0], x0, x1, shrink);
Toshihiro Shimizu 890ddd
			m_y++;
Toshihiro Shimizu 890ddd
			if (m_tempBuffer && m_y == ly) {
Shinya Kitaoka 79e39b
				m_tempBuffer.reset();
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		int y = m_info.m_ly - 1 - m_y;
Toshihiro Shimizu 890ddd
		if (y < 0)
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
		m_y++;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 79e39b
		png_bytep row_pointer = m_rowBuffer.get();
Toshihiro Shimizu 890ddd
		png_read_row(m_png_ptr, row_pointer, NULL);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		writeRow(buffer);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (m_tempBuffer && m_y == ly) {
Shinya Kitaoka 79e39b
			m_tempBuffer.reset();
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void readLine(short *buffer, int x0, int x1, int shrink)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		int ly = m_info.m_ly;
Toshihiro Shimizu 890ddd
		if (!m_tempBuffer) {
Toshihiro Shimizu 890ddd
			int lx = m_info.m_lx;
Toshihiro Shimizu 890ddd
			int channels = png_get_channels(m_png_ptr, m_info_ptr);
Toshihiro Shimizu 890ddd
			int rowBytes = png_get_rowbytes(m_png_ptr, m_info_ptr);
Toshihiro Shimizu 890ddd
			if (m_interlace_type == 1) {
Toshihiro Shimizu 890ddd
				if (channels == 1 || channels == 2) {
Toshihiro Shimizu 890ddd
					if (m_bit_depth < 8) // (m_bit_depth == 1 || m_bit_depth == 2 || m_bit_depth == 4)
Shinya Kitaoka 79e39b
						m_tempBuffer.reset(new unsigned char[ly * lx * 3]);
Toshihiro Shimizu 890ddd
					else
Shinya Kitaoka 79e39b
						m_tempBuffer.reset(new unsigned char[ly * rowBytes * 4]);
Toshihiro Shimizu 890ddd
				} else {
Shinya Kitaoka 79e39b
					m_tempBuffer.reset(new unsigned char[ly * rowBytes]);
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
fukasawa e60969
		if (png_get_interlace_type(m_png_ptr, m_info_ptr) == PNG_INTERLACE_ADAM7) {
Toshihiro Shimizu 890ddd
			readLineInterlace(&buffer[0], x0, x1, shrink);
Toshihiro Shimizu 890ddd
			m_y++;
Toshihiro Shimizu 890ddd
			if (m_tempBuffer && m_y == ly) {
Shinya Kitaoka 79e39b
				m_tempBuffer.reset();
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		int y = m_info.m_ly - 1 - m_y;
Toshihiro Shimizu 890ddd
		if (y < 0)
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
		m_y++;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 79e39b
		png_bytep row_pointer = m_rowBuffer.get();
Toshihiro Shimizu 890ddd
		png_read_row(m_png_ptr, row_pointer, NULL);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		writeRow(buffer);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (m_tempBuffer && m_y == ly) {
Shinya Kitaoka 79e39b
			m_tempBuffer.reset();
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int skipLines(int lineCount)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		for (int i = 0; i < lineCount; i++) {
Toshihiro Shimizu 890ddd
			if (m_interlace_type == 1 && m_info.m_lx > 4) // pezza. Studiare il codice
Toshihiro Shimizu 890ddd
			{
Toshihiro Shimizu 890ddd
				int channels = png_get_channels(m_png_ptr, m_info_ptr);
Toshihiro Shimizu 890ddd
				char *lineBuffer = (char *)malloc(4 * m_info.m_lx * sizeof(char));
Toshihiro Shimizu 890ddd
				readLine(lineBuffer, 0, m_info.m_lx - 1, 1);
Toshihiro Shimizu 890ddd
				free(lineBuffer);
Toshihiro Shimizu 890ddd
			} else {
Toshihiro Shimizu 890ddd
				m_y++;
Shinya Kitaoka 79e39b
				png_bytep row_pointer = m_rowBuffer.get();
Toshihiro Shimizu 890ddd
				png_read_row(m_png_ptr, row_pointer, NULL);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		return lineCount;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	Tiio::RowOrder getRowOrder() const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return Tiio::TOP2BOTTOM;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void writeRow(char *buffer)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		if (m_color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
Toshihiro Shimizu 890ddd
			m_color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
Toshihiro Shimizu 890ddd
			if (m_bit_depth == 16) {
Toshihiro Shimizu 890ddd
				TPixel32 *pix = (TPixel32 *)buffer;
Toshihiro Shimizu 890ddd
				int i = -2;
Toshihiro Shimizu 890ddd
				for (int j = 0; j < m_info.m_lx; j++) {
Toshihiro Shimizu 890ddd
#if defined(TNZ_MACHINE_CHANNEL_ORDER_MRGB)
Toshihiro Shimizu 890ddd
					pix[j].m = m_rowBuffer[i = i + 2];
Toshihiro Shimizu 890ddd
					pix[j].r = m_rowBuffer[i = i + 2];
Toshihiro Shimizu 890ddd
					pix[j].g = m_rowBuffer[i = i + 2];
Toshihiro Shimizu 890ddd
					pix[j].b = m_rowBuffer[i = i + 2];
Toshihiro Shimizu 890ddd
#elif defined(TNZ_MACHINE_CHANNEL_ORDER_RGBM)
Toshihiro Shimizu 890ddd
					pix[j].r = m_rowBuffer[i = i + 2];
Toshihiro Shimizu 890ddd
					pix[j].g = m_rowBuffer[i = i + 2];
Toshihiro Shimizu 890ddd
					pix[j].b = m_rowBuffer[i = i + 2];
Toshihiro Shimizu 890ddd
					pix[j].m = m_rowBuffer[i = i + 2];
Toshihiro Shimizu 890ddd
#elif defined(TNZ_MACHINE_CHANNEL_ORDER_BGRM)
Toshihiro Shimizu 890ddd
					pix[j].b = m_rowBuffer[i = i + 2];
Toshihiro Shimizu 890ddd
					pix[j].g = m_rowBuffer[i = i + 2];
Toshihiro Shimizu 890ddd
					pix[j].r = m_rowBuffer[i = i + 2];
Toshihiro Shimizu 890ddd
					pix[j].m = m_rowBuffer[i = i + 2];
Toshihiro Shimizu 890ddd
#elif defined(TNZ_MACHINE_CHANNEL_ORDER_MBGR)
Toshihiro Shimizu 890ddd
					pix[j].m = m_rowBuffer[i = i + 2];
Toshihiro Shimizu 890ddd
					pix[j].b = m_rowBuffer[i = i + 2];
Toshihiro Shimizu 890ddd
					pix[j].g = m_rowBuffer[i = i + 2];
Toshihiro Shimizu 890ddd
					pix[j].r = m_rowBuffer[i = i + 2];
Toshihiro Shimizu 890ddd
#else
Campbell Barton 42d601
#error				"unknown channel order"
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			} else {
Toshihiro Shimizu 890ddd
				TPixel32 *pix = (TPixel32 *)buffer;
Toshihiro Shimizu 890ddd
				int i = 0;
Toshihiro Shimizu 890ddd
				for (int j = 0; j < m_info.m_lx; j++) {
Toshihiro Shimizu 890ddd
#if defined(TNZ_MACHINE_CHANNEL_ORDER_MRGB)
Toshihiro Shimizu 890ddd
					pix[j].m = m_rowBuffer[i++];
Toshihiro Shimizu 890ddd
					pix[j].r = m_rowBuffer[i++];
Toshihiro Shimizu 890ddd
					pix[j].g = m_rowBuffer[i++];
Toshihiro Shimizu 890ddd
					pix[j].b = m_rowBuffer[i++];
Toshihiro Shimizu 890ddd
#elif defined(TNZ_MACHINE_CHANNEL_ORDER_RGBM)
Toshihiro Shimizu 890ddd
					pix[j].r = m_rowBuffer[i++];
Toshihiro Shimizu 890ddd
					pix[j].g = m_rowBuffer[i++];
Toshihiro Shimizu 890ddd
					pix[j].b = m_rowBuffer[i++];
Toshihiro Shimizu 890ddd
					pix[j].m = m_rowBuffer[i++];
Toshihiro Shimizu 890ddd
#elif defined(TNZ_MACHINE_CHANNEL_ORDER_BGRM)
Toshihiro Shimizu 890ddd
					pix[j].b = m_rowBuffer[i++];
Toshihiro Shimizu 890ddd
					pix[j].g = m_rowBuffer[i++];
Toshihiro Shimizu 890ddd
					pix[j].r = m_rowBuffer[i++];
Toshihiro Shimizu 890ddd
					pix[j].m = m_rowBuffer[i++];
Toshihiro Shimizu 890ddd
#elif defined(TNZ_MACHINE_CHANNEL_ORDER_MBGR)
Toshihiro Shimizu 890ddd
					pix[j].m = m_rowBuffer[i++];
Toshihiro Shimizu 890ddd
					pix[j].b = m_rowBuffer[i++];
Toshihiro Shimizu 890ddd
					pix[j].g = m_rowBuffer[i++];
Toshihiro Shimizu 890ddd
					pix[j].r = m_rowBuffer[i++];
Toshihiro Shimizu 890ddd
#else
Campbell Barton 42d601
#error				"unknown channel order"
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		} else //qui gestisce RGB senza alpha.
Toshihiro Shimizu 890ddd
		{	  // grayscale e' gestito come RGB perche' si usa png_set_gray_to_rgb
Toshihiro Shimizu 890ddd
			if (m_bit_depth == 16) {
Toshihiro Shimizu 890ddd
				TPixel32 *pix = (TPixel32 *)buffer;
Toshihiro Shimizu 890ddd
				int i = -2;
Toshihiro Shimizu 890ddd
				for (int j = 0; j < m_info.m_lx; j++) {
Toshihiro Shimizu 890ddd
#if defined(TNZ_MACHINE_CHANNEL_ORDER_MRGB) || defined(TNZ_MACHINE_CHANNEL_ORDER_RGBM)
Toshihiro Shimizu 890ddd
					pix[j].r = m_rowBuffer[i = i + 2];
Toshihiro Shimizu 890ddd
					pix[j].g = m_rowBuffer[i = i + 2];
Toshihiro Shimizu 890ddd
					pix[j].b = m_rowBuffer[i = i + 2];
Toshihiro Shimizu 890ddd
#elif defined(TNZ_MACHINE_CHANNEL_ORDER_MBGR) || defined(TNZ_MACHINE_CHANNEL_ORDER_BGRM)
Toshihiro Shimizu 890ddd
					pix[j].b = m_rowBuffer[i = i + 2];
Toshihiro Shimizu 890ddd
					pix[j].g = m_rowBuffer[i = i + 2];
Toshihiro Shimizu 890ddd
					pix[j].r = m_rowBuffer[i = i + 2];
Toshihiro Shimizu 890ddd
#else
Campbell Barton 42d601
#error				"unknown channel order"
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
					pix[j].m = 255;
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			} else {
Toshihiro Shimizu 890ddd
				TPixel32 *pix = (TPixel32 *)buffer;
Toshihiro Shimizu 890ddd
				int i = 0;
Toshihiro Shimizu 890ddd
				for (int j = 0; j < m_info.m_lx; j++) {
Toshihiro Shimizu 890ddd
#if defined(TNZ_MACHINE_CHANNEL_ORDER_MRGB) || defined(TNZ_MACHINE_CHANNEL_ORDER_RGBM)
Toshihiro Shimizu 890ddd
					pix[j].r = m_rowBuffer[i++];
Toshihiro Shimizu 890ddd
					pix[j].g = m_rowBuffer[i++];
Toshihiro Shimizu 890ddd
					pix[j].b = m_rowBuffer[i++];
Toshihiro Shimizu 890ddd
#elif defined(TNZ_MACHINE_CHANNEL_ORDER_MBGR) || defined(TNZ_MACHINE_CHANNEL_ORDER_BGRM)
Toshihiro Shimizu 890ddd
					pix[j].b = m_rowBuffer[i++];
Toshihiro Shimizu 890ddd
					pix[j].g = m_rowBuffer[i++];
Toshihiro Shimizu 890ddd
					pix[j].r = m_rowBuffer[i++];
Toshihiro Shimizu 890ddd
#else
Campbell Barton 42d601
#error				"unknown channel order"
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
					pix[j].m = 255;
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void writeRow(short *buffer)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		if (m_color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
Toshihiro Shimizu 890ddd
			m_color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
Toshihiro Shimizu 890ddd
			TPixel64 *pix = (TPixel64 *)buffer;
Toshihiro Shimizu 890ddd
			int i = -2; //0;
Toshihiro Shimizu 890ddd
			for (int j = 0; j < m_info.m_lx; j++) {
Toshihiro Shimizu 890ddd
#if defined(TNZ_MACHINE_CHANNEL_ORDER_MRGB) || defined(TNZ_MACHINE_CHANNEL_ORDER_RGBM)
Toshihiro Shimizu 890ddd
				pix[j].r = mySwap(m_rowBuffer[i = i + 2]); //i++
Toshihiro Shimizu 890ddd
				pix[j].g = mySwap(m_rowBuffer[i = i + 2]);
Toshihiro Shimizu 890ddd
				pix[j].b = mySwap(m_rowBuffer[i = i + 2]);
Toshihiro Shimizu 890ddd
				pix[j].m = mySwap(m_rowBuffer[i = i + 2]);
Toshihiro Shimizu 890ddd
#elif defined(TNZ_MACHINE_CHANNEL_ORDER_MBGR) || defined(TNZ_MACHINE_CHANNEL_ORDER_BGRM)
Toshihiro Shimizu 890ddd
				pix[j].b = mySwap(m_rowBuffer[i = i + 2]); //i++
Toshihiro Shimizu 890ddd
				pix[j].g = mySwap(m_rowBuffer[i = i + 2]);
Toshihiro Shimizu 890ddd
				pix[j].r = mySwap(m_rowBuffer[i = i + 2]);
Toshihiro Shimizu 890ddd
				pix[j].m = mySwap(m_rowBuffer[i = i + 2]);
Toshihiro Shimizu 890ddd
#else
Campbell Barton 42d601
#error			"unknown channel order"
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
				//pix[j].m = 255;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		} else //qui gestisce RGB senza alpha.
Toshihiro Shimizu 890ddd
		{	  // grayscale e' gestito come RGB perche' si usa png_set_gray_to_rgb
Toshihiro Shimizu 890ddd
			TPixel64 *pix = (TPixel64 *)buffer;
Toshihiro Shimizu 890ddd
			int i = -2;
Toshihiro Shimizu 890ddd
			for (int j = 0; j < m_info.m_lx; j++) {
Toshihiro Shimizu 890ddd
#if defined(TNZ_MACHINE_CHANNEL_ORDER_MRGB) || defined(TNZ_MACHINE_CHANNEL_ORDER_RGBM)
Toshihiro Shimizu 890ddd
				pix[j].r = mySwap(m_rowBuffer[i = i + 2]);
Toshihiro Shimizu 890ddd
				pix[j].g = mySwap(m_rowBuffer[i = i + 2]);
Toshihiro Shimizu 890ddd
				pix[j].b = mySwap(m_rowBuffer[i = i + 2]);
Toshihiro Shimizu 890ddd
#elif defined(TNZ_MACHINE_CHANNEL_ORDER_MBGR) || defined(TNZ_MACHINE_CHANNEL_ORDER_BGRM)
Toshihiro Shimizu 890ddd
				pix[j].b = mySwap(m_rowBuffer[i = i + 2]);
Toshihiro Shimizu 890ddd
				pix[j].g = mySwap(m_rowBuffer[i = i + 2]);
Toshihiro Shimizu 890ddd
				pix[j].r = mySwap(m_rowBuffer[i = i + 2]);
Toshihiro Shimizu 890ddd
#else
Campbell Barton 42d601
#error			"unknown channel order"
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
				pix[j].m = mySwap(255);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void copyPixel(int count, int dstX, int dstDx, int dstY)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		int channels = png_get_channels(m_png_ptr, m_info_ptr);
Toshihiro Shimizu 890ddd
		int rowBytes = png_get_rowbytes(m_png_ptr, m_info_ptr);
Toshihiro Shimizu 890ddd
		int lx = m_info.m_lx;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if ((channels == 4 || channels == 3) && m_bit_depth == 16) {
Toshihiro Shimizu 890ddd
			for (int i = 0; i < count; i += 2) {
Toshihiro Shimizu 890ddd
				for (int j = 0; j < channels * 2; j++) {
Shinya Kitaoka 79e39b
					(m_tempBuffer.get() + (dstY * rowBytes))[(i * dstDx + dstX) * channels + j] = m_rowBuffer[i * channels + j];
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		} else if (channels == 2 && m_bit_depth == 16) {
Toshihiro Shimizu 890ddd
			for (int i = 0; i < count; i += 2) {
Toshihiro Shimizu 890ddd
				for (int j = 0; j < 4 * 2; j++) {
Shinya Kitaoka 79e39b
					(m_tempBuffer.get() + (dstY * rowBytes * 4))[(i * dstDx + dstX) * 4 + j] = m_rowBuffer[i * 4 + j];
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		} else if (channels == 1 && m_bit_depth == 16) {
Toshihiro Shimizu 890ddd
			for (int i = 0; i < count; i += 2) {
Toshihiro Shimizu 890ddd
				for (int j = 0; j < 3 * 2; j++) {
Shinya Kitaoka 79e39b
					(m_tempBuffer.get() + (dstY * rowBytes * 4))[(i * dstDx + dstX) * 3 + j] = m_rowBuffer[i * 3 + j];
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		} else if (channels == 1 && m_bit_depth == 8) {
Toshihiro Shimizu 890ddd
			for (int i = 0; i < count; i++) {
Toshihiro Shimizu 890ddd
				for (int j = 0; j < 3; j++) {
Shinya Kitaoka 79e39b
					(m_tempBuffer.get() + (dstY * rowBytes * 4))[(i * dstDx + dstX) * 3 + j] = m_rowBuffer[i * 3 + j];
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		} else if (channels == 2 && m_bit_depth == 8) {
Toshihiro Shimizu 890ddd
			for (int i = 0; i < count; i++) {
Toshihiro Shimizu 890ddd
				for (int j = 0; j < 4; j++) {
Shinya Kitaoka 79e39b
					(m_tempBuffer.get() + (dstY * rowBytes * 4))[(i * dstDx + dstX) * 4 + j] = m_rowBuffer[i * 4 + j];
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		} else if ((channels == 1 || channels == 2) && m_bit_depth < 8) {
Toshihiro Shimizu 890ddd
			for (int i = 0; i < count; i++) {
Toshihiro Shimizu 890ddd
				for (int j = 0; j < 3; j++) {
Shinya Kitaoka 79e39b
					(m_tempBuffer.get() + (dstY * lx * 3))[(i * dstDx + dstX) * 3 + j] = m_rowBuffer[i * 3 + j];
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			for (int i = 0; i < count; i++) {
Toshihiro Shimizu 890ddd
				for (int j = 0; j < channels; j++) {
Shinya Kitaoka 79e39b
					(m_tempBuffer.get() + (dstY * rowBytes))[(i * dstDx + dstX) * channels + j] = m_rowBuffer[i * channels + j];
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void readLineInterlace(char *buffer, int x0, int x1, int shrink)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		//m_png_ptr->row_number è l'indice di riga che scorre quando chiamo la png_read_row
fukasawa e60969
		int rowNumber = png_get_current_row_number(m_png_ptr);
Toshihiro Shimizu 890ddd
		//numRows è il numero di righe processate in ogni passo
fukasawa e60969
		int numRows = (int)png_get_image_height(m_png_ptr, m_info_ptr) / 8;
Toshihiro Shimizu 890ddd
fukasawa e60969
		int passPng = png_get_current_pass_number(m_png_ptr); 
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		int passRow = 5 + (m_y & 1); //passo desiderato per la riga corrente
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		int channels = png_get_channels(m_png_ptr, m_info_ptr);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		int rowBytes = png_get_rowbytes(m_png_ptr, m_info_ptr);
Shinya Kitaoka 79e39b
		png_bytep row_pointer = m_rowBuffer.get();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		int lx = m_info.m_lx;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		while (passPng <= passRow && rowNumber <= numRows) //finchè il passo d'interlacciamento è minore o uguale
Toshihiro Shimizu 890ddd
														   // <             //del passo desiderato effettua tante volte le lettura della riga
Toshihiro Shimizu 890ddd
														   //quant'è il passo desiderato per quella riga
Toshihiro Shimizu 890ddd
		{
fukasawa e60969
			rowNumber = png_get_current_row_number(m_png_ptr);
Toshihiro Shimizu 890ddd
			png_read_row(m_png_ptr, row_pointer, NULL);
fukasawa e60969
			numRows = png_get_image_height(m_png_ptr, m_info_ptr);
Toshihiro Shimizu 890ddd
			//devo memorizzare la riga letta nel buffer di appoggio in base al passo di riga
Toshihiro Shimizu 890ddd
			//e al blocchetto di appartenenza della riga
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			//copio i pixel che desidero nel buffer temporaneo
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			//il membro di PngReader copyPixel deve tener conto della riga processata
Toshihiro Shimizu 890ddd
			//e del passo che si è effettuato ( e in base a quello so quanti pixel copiare!)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (m_bit_depth == 16) {
Toshihiro Shimizu 890ddd
				if (passPng == 0)
Toshihiro Shimizu 890ddd
					copyPixel(lx / 4, 0, 8, rowNumber * 8);
Toshihiro Shimizu 890ddd
				else if (passPng == 1)
Toshihiro Shimizu 890ddd
					copyPixel(lx / 4, 8, 8, rowNumber * 8);
Toshihiro Shimizu 890ddd
				else if (passPng == 2)
Toshihiro Shimizu 890ddd
					copyPixel(lx / 2, 0, 4, rowNumber * 8 + 4);
Toshihiro Shimizu 890ddd
				else if (passPng == 3)
Toshihiro Shimizu 890ddd
					copyPixel(lx / 2, 4, 4, rowNumber * 4);
Toshihiro Shimizu 890ddd
				else if (passPng == 4)
Toshihiro Shimizu 890ddd
					copyPixel(lx, 0, 2, rowNumber * 4 + 2);
Toshihiro Shimizu 890ddd
				else if (passPng == 5)
Toshihiro Shimizu 890ddd
					copyPixel(lx, 2, 2, rowNumber * 2);
Toshihiro Shimizu 890ddd
				else if (passPng == 6)
Toshihiro Shimizu 890ddd
					copyPixel(2 * lx, 0, 1, rowNumber * 2 + 1);
Toshihiro Shimizu 890ddd
			} else {
Toshihiro Shimizu 890ddd
				if (passPng == 0)
Toshihiro Shimizu 890ddd
					copyPixel((lx + 7) / 8, 0, 8, rowNumber * 8);
Toshihiro Shimizu 890ddd
				else if (passPng == 1)
Toshihiro Shimizu 890ddd
					copyPixel((lx + 3) / 8, 4, 8, rowNumber * 8);
Toshihiro Shimizu 890ddd
				else if (passPng == 2)
Toshihiro Shimizu 890ddd
					copyPixel((lx + 3) / 4, 0, 4, rowNumber * 8 + 4);
Toshihiro Shimizu 890ddd
				else if (passPng == 3)
Toshihiro Shimizu 890ddd
					copyPixel((lx + 1) / 4, 2, 4, rowNumber * 4);
Toshihiro Shimizu 890ddd
				else if (passPng == 4)
Toshihiro Shimizu 890ddd
					copyPixel((lx + 1) / 2, 0, 2, rowNumber * 4 + 2);
Toshihiro Shimizu 890ddd
				else if (passPng == 5)
Toshihiro Shimizu 890ddd
					copyPixel(lx / 2, 1, 2, rowNumber * 2);
Toshihiro Shimizu 890ddd
				else if (passPng == 6)
Toshihiro Shimizu 890ddd
					copyPixel(lx, 0, 1, rowNumber * 2 + 1);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
fukasawa e60969
			passPng = png_get_current_pass_number(m_png_ptr);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// fase di copia
Toshihiro Shimizu 890ddd
		if (channels == 1 || channels == 2) {
Toshihiro Shimizu 890ddd
			if (m_bit_depth < 8)
Shinya Kitaoka 79e39b
				memcpy(m_rowBuffer.get(), m_tempBuffer.get() + ((m_y)*lx * 3), lx * 3);
Toshihiro Shimizu 890ddd
			else
Shinya Kitaoka 79e39b
				memcpy(m_rowBuffer.get(), m_tempBuffer.get() + ((m_y)*rowBytes * 4), rowBytes * 4);
Toshihiro Shimizu 890ddd
		} else {
Shinya Kitaoka 79e39b
			memcpy(m_rowBuffer.get(), m_tempBuffer.get() + ((m_y)*rowBytes), rowBytes);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// fase di copia vecchia
Toshihiro Shimizu 890ddd
		//memcpy(m_rowBuffer, m_tempBuffer+((m_y)*rowBytes), rowBytes);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//tutto quello che segue lo metto in una funzione in cui scrivo il buffer di restituzione della readLine
Toshihiro Shimizu 890ddd
		//è una funzione comune alle ReadLine
Toshihiro Shimizu 890ddd
		writeRow(buffer);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void readLineInterlace(short *buffer, int x0, int x1, int shrink)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		//m_png_ptr->row_number è l'indice di riga che scorre quando chiamo la png_read_row
fukasawa e60969
		int rowNumber = png_get_current_row_number(m_png_ptr);
Toshihiro Shimizu 890ddd
		//numRows è il numero di righe processate in ogni passo
fukasawa e60969
		int numRows = png_get_image_height(m_png_ptr, m_info_ptr) / 8;
Toshihiro Shimizu 890ddd
fukasawa e60969
		int passPng = png_get_current_pass_number(m_png_ptr); //conosco il passo d'interlacciamento
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		int passRow = 5 + (m_y & 1); //passo desiderato per la riga corrente
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		int channels = png_get_channels(m_png_ptr, m_info_ptr);
Toshihiro Shimizu 890ddd
		int lx = m_info.m_lx;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		int rowBytes = png_get_rowbytes(m_png_ptr, m_info_ptr);
Shinya Kitaoka 79e39b
		png_bytep row_pointer = m_rowBuffer.get();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		while (passPng <= passRow && rowNumber < numRows) //finchè il passo d'interlacciamento è minore o uguale
Toshihiro Shimizu 890ddd
														  //del passo desiderato effettua tante volte le lettura della riga
Toshihiro Shimizu 890ddd
														  //quant'è il passo desiderato per quella riga
Toshihiro Shimizu 890ddd
		{
fukasawa e60969
			rowNumber = png_get_current_row_number(m_png_ptr);
Toshihiro Shimizu 890ddd
			png_read_row(m_png_ptr, row_pointer, NULL);
fukasawa e60969
			numRows = png_get_image_height(m_png_ptr, m_info_ptr);
Toshihiro Shimizu 890ddd
			int lx = m_info.m_lx;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			//devo memorizzare la riga letta nel buffer di appoggio in base al passo di riga
Toshihiro Shimizu 890ddd
			//e al blocchetto di appartenenza della riga
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			//copio i pixel che desidero nel buffer temporaneo
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			//il membro di PngReader copyPixel deve tener conto della riga processata
Toshihiro Shimizu 890ddd
			//e del passo che si è effettuato ( e in base a quello so quanti pixel copiare!)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			int channels = png_get_channels(m_png_ptr, m_info_ptr);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (passPng == 0)
Toshihiro Shimizu 890ddd
				copyPixel(lx / 4, 0, 8, rowNumber * 8);
Toshihiro Shimizu 890ddd
			else if (passPng == 1)
Toshihiro Shimizu 890ddd
				copyPixel(lx / 4, 8, 8, rowNumber * 8);
Toshihiro Shimizu 890ddd
			else if (passPng == 2)
Toshihiro Shimizu 890ddd
				copyPixel(lx / 2, 0, 4, rowNumber * 8 + 4);
Toshihiro Shimizu 890ddd
			else if (passPng == 3)
Toshihiro Shimizu 890ddd
				copyPixel(lx / 2, 4, 4, rowNumber * 4);
Toshihiro Shimizu 890ddd
			else if (passPng == 4)
Toshihiro Shimizu 890ddd
				copyPixel(lx, 0, 2, rowNumber * 4 + 2);
Toshihiro Shimizu 890ddd
			else if (passPng == 5)
Toshihiro Shimizu 890ddd
				copyPixel(lx, 2, 2, rowNumber * 2);
Toshihiro Shimizu 890ddd
			else if (passPng == 6)
Toshihiro Shimizu 890ddd
				copyPixel(2 * lx, 0, 1, rowNumber * 2 + 1);
Toshihiro Shimizu 890ddd
fukasawa e60969
			passPng = png_get_current_pass_number(m_png_ptr);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// fase di copia
Toshihiro Shimizu 890ddd
		if (channels == 1 || channels == 2) {
Shinya Kitaoka 79e39b
			memcpy(m_rowBuffer.get(), m_tempBuffer.get() + ((m_y)*rowBytes * 4), rowBytes * 4);
Toshihiro Shimizu 890ddd
		} else {
Shinya Kitaoka 79e39b
			memcpy(m_rowBuffer.get(), m_tempBuffer.get() + ((m_y)*rowBytes), rowBytes);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// fase di copia
Toshihiro Shimizu 890ddd
		//memcpy(m_rowBuffer, m_tempBuffer+((m_y)*rowBytes), rowBytes);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//tutto quello che segue lo metto in una funzione in cui scrivo il buffer di restituzione della readLine
Toshihiro Shimizu 890ddd
		//è una funzione comune alle ReadLine
Toshihiro Shimizu 890ddd
		writeRow(buffer);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=========================================================
Toshihiro Shimizu 890ddd
fukasawa 13abb6
Toshihiro Shimizu 890ddd
Tiio::PngWriterProperties::PngWriterProperties()
Toshihiro Shimizu 890ddd
	: m_matte("Alpha Channel", true)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	bind(m_matte);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=========================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class PngWriter : public Tiio::Writer
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	png_structp m_png_ptr;
Toshihiro Shimizu 890ddd
	png_infop m_info_ptr;
Toshihiro Shimizu 890ddd
	FILE *m_chan;
Toshihiro Shimizu 890ddd
	bool m_matte;
Shinya Kitaoka 3bfa54
	std::vector<tpixel> *m_colormap;</tpixel>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	PngWriter();
Toshihiro Shimizu 890ddd
	~PngWriter();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void open(FILE *file, const TImageInfo &info);
Toshihiro Shimizu 890ddd
	void writeLine(char *buffer);
Toshihiro Shimizu 890ddd
	virtual void writeLine(short *buffer);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	Tiio::RowOrder getRowOrder() const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return Tiio::TOP2BOTTOM;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void flush();
Toshihiro Shimizu 890ddd
	virtual bool write64bitSupported() const { return true; }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
PngWriter::PngWriter()
Toshihiro Shimizu 890ddd
	: m_png_ptr(0), m_info_ptr(0), m_matte(true), m_colormap(0)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
PngWriter::~PngWriter()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (m_png_ptr) {
Toshihiro Shimizu 890ddd
		png_destroy_write_struct(
Toshihiro Shimizu 890ddd
			&m_png_ptr,
Toshihiro Shimizu 890ddd
			&m_info_ptr);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	if (m_chan) {
Toshihiro Shimizu 890ddd
		fflush(m_chan);
Toshihiro Shimizu 890ddd
		m_chan = 0;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
png_color palette[256];
Toshihiro Shimizu 890ddd
png_byte alpha[1];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void PngWriter::open(FILE *file, const TImageInfo &info)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_info = info;
Toshihiro Shimizu 890ddd
	m_png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
Toshihiro Shimizu 890ddd
										(png_voidp)0, //user_error_ptr,
Toshihiro Shimizu 890ddd
										0,			  //user_error_fn,
Toshihiro Shimizu 890ddd
										0);			  //user_warning_fn);
Toshihiro Shimizu 890ddd
	if (!m_png_ptr)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	m_info_ptr = png_create_info_struct(m_png_ptr);
Toshihiro Shimizu 890ddd
	if (!m_info_ptr) {
Toshihiro Shimizu 890ddd
		png_destroy_write_struct(&m_png_ptr, (png_infopp)0);
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_chan = file;
Toshihiro Shimizu 890ddd
	png_init_io(m_png_ptr, m_chan);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!m_properties)
Toshihiro Shimizu 890ddd
		m_properties = new Tiio::PngWriterProperties();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TBoolProperty *alphaProp = (TBoolProperty *)(m_properties->getProperty("Alpha Channel"));
Toshihiro Shimizu 890ddd
	TPointerProperty *colormap = (TPointerProperty *)(m_properties->getProperty("Colormap"));
Toshihiro Shimizu 890ddd
	m_matte = (alphaProp && alphaProp->getValue()) ? true : false;
Toshihiro Shimizu 890ddd
	if (colormap)
Toshihiro Shimizu 890ddd
		m_colormap = (vector<tpixel> *)colormap->getValue();</tpixel>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TUINT32 x_pixels_per_meter = tround(m_info.m_dpix / 0.0254);
Toshihiro Shimizu 890ddd
	TUINT32 y_pixels_per_meter = tround(m_info.m_dpiy / 0.0254);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!m_colormap)
Toshihiro Shimizu 890ddd
		png_set_IHDR(m_png_ptr, m_info_ptr,
Toshihiro Shimizu 890ddd
					 m_info.m_lx, m_info.m_ly,
Toshihiro Shimizu 890ddd
					 info.m_bitsPerSample, m_matte ? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_RGB,
Toshihiro Shimizu 890ddd
					 PNG_INTERLACE_NONE,
Toshihiro Shimizu 890ddd
					 PNG_COMPRESSION_TYPE_DEFAULT,
Toshihiro Shimizu 890ddd
					 PNG_FILTER_TYPE_DEFAULT);
Toshihiro Shimizu 890ddd
	else {
Toshihiro Shimizu 890ddd
		png_set_IHDR(m_png_ptr, m_info_ptr,
Toshihiro Shimizu 890ddd
					 m_info.m_lx, m_info.m_ly,
Toshihiro Shimizu 890ddd
					 8, PNG_COLOR_TYPE_PALETTE,
Toshihiro Shimizu 890ddd
					 PNG_INTERLACE_NONE,
Toshihiro Shimizu 890ddd
					 PNG_COMPRESSION_TYPE_DEFAULT,
Toshihiro Shimizu 890ddd
					 PNG_FILTER_TYPE_DEFAULT);
Toshihiro Shimizu 890ddd
		for (unsigned int i = 0; i < m_colormap->size(); i++) {
Toshihiro Shimizu 890ddd
			/*unsigned char red = (i>>5)&0x7;
Toshihiro Shimizu 890ddd
			unsigned char green = (i>>2)&0x7;
Toshihiro Shimizu 890ddd
			unsigned char blue = i&0x3;
Toshihiro Shimizu 890ddd
			palette[i].red = (red>>1) | (red<<2) | (red<<5);
Toshihiro Shimizu 890ddd
			palette[i].green = (green>>1) | (green<<2) | (green<<5);
Toshihiro Shimizu 890ddd
			palette[i].blue = blue | (blue<<2) | (blue<<4) | (blue<<6);
Toshihiro Shimizu 890ddd
			if (red==0 && green==0) alpha[i] = 0; else if (blue==0 && green==0) alpha[i] = 128; else alpha[i] = 255;*/
Toshihiro Shimizu 890ddd
			palette[i].red = (*m_colormap)[i].r;
Toshihiro Shimizu 890ddd
			palette[i].green = (*m_colormap)[i].g;
Toshihiro Shimizu 890ddd
			palette[i].blue = (*m_colormap)[i].b;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		png_set_PLTE(m_png_ptr, m_info_ptr, palette, m_colormap->size());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//png_set_dither(m_png_ptr, palette, 256, 256, 0, 1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#if defined(TNZ_MACHINE_CHANNEL_ORDER_MBGR)
Toshihiro Shimizu 890ddd
	png_set_bgr(m_png_ptr);
Toshihiro Shimizu 890ddd
	png_set_swap_alpha(m_png_ptr);
Toshihiro Shimizu 890ddd
#elif defined(TNZ_MACHINE_CHANNEL_ORDER_BGRM)
Toshihiro Shimizu 890ddd
	png_set_bgr(m_png_ptr);
Toshihiro Shimizu 890ddd
#elif defined(TNZ_MACHINE_CHANNEL_ORDER_MRGB)
Toshihiro Shimizu 890ddd
	png_set_swap_alpha(m_png_ptr);
Toshihiro Shimizu 890ddd
#elif !defined(TNZ_MACHINE_CHANNEL_ORDER_RGBM)
Campbell Barton 42d601
#error	"unknownchannel order"
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	png_write_info(m_png_ptr, m_info_ptr);
fukasawa e60969
	png_set_pHYs(m_png_ptr, m_info_ptr, x_pixels_per_meter, y_pixels_per_meter, 1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_colormap && m_matte) {
Toshihiro Shimizu 890ddd
		alpha[0] = 0;
fukasawa e60969
		//png_set_tRNS(m_png_ptr, m_info_ptr, alpha, 1, PNG_COLOR_TYPE_PALETTE);
fukasawa e60969
		png_color_16 bgcolor;
fukasawa e60969
		bgcolor.index = 0;
fukasawa e60969
		png_set_tRNS(m_png_ptr, m_info_ptr, alpha, 1, &bgcolor);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void PngWriter::flush()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	png_write_end(m_png_ptr, m_info_ptr);
Toshihiro Shimizu 890ddd
	fflush(m_chan);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void PngWriter::writeLine(short *buffer)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		TPixel64 *pix = (TPixel64 *)buffer;
Toshihiro Shimizu 890ddd
		unsigned short *tmp;
Toshihiro Shimizu 890ddd
		tmp = (unsigned short *)malloc((m_info.m_lx + 1) * 3);
Toshihiro Shimizu 890ddd
		//unsigned short tmp[10000];
Toshihiro Shimizu 890ddd
		int k = 0;
Toshihiro Shimizu 890ddd
		for (int j = 0; j < m_info.m_lx; j++) {
Toshihiro Shimizu 890ddd
#if defined(TNZ_MACHINE_CHANNEL_ORDER_MRGB) || defined(TNZ_MACHINE_CHANNEL_ORDER_RGBM)
Toshihiro Shimizu 890ddd
			tmp[k++] = mySwap(pix->r);
Toshihiro Shimizu 890ddd
			tmp[k++] = mySwap(pix->g);
Toshihiro Shimizu 890ddd
			tmp[k++] = mySwap(pix->b);
Toshihiro Shimizu 890ddd
#elif defined(TNZ_MACHINE_CHANNEL_ORDER_MBGR) || defined(TNZ_MACHINE_CHANNEL_ORDER_BGRM)
Toshihiro Shimizu 890ddd
			tmp[k++] = mySwap(pix->b);
Toshihiro Shimizu 890ddd
			tmp[k++] = mySwap(pix->g);
Toshihiro Shimizu 890ddd
			tmp[k++] = mySwap(pix->r);
Toshihiro Shimizu 890ddd
#else
Campbell Barton 42d601
#error		"unknown channel order"
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
			if (m_matte)
Toshihiro Shimizu 890ddd
				tmp[k++] = mySwap(pix->m);
Toshihiro Shimizu 890ddd
			++pix;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		png_write_row(m_png_ptr, (unsigned char *)tmp);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=========================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void PngWriter::writeLine(char *buffer)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	//TBoolProperty* alphaProp = (TBoolProperty*)(m_properties->getProperty("Alpha Channel"));
Toshihiro Shimizu 890ddd
	if (m_matte || m_colormap) {
Toshihiro Shimizu 890ddd
		png_bytep row_pointer = (unsigned char *)buffer;
Toshihiro Shimizu 890ddd
		png_write_row(m_png_ptr, row_pointer);
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		unsigned char *tmp = 0;
Toshihiro Shimizu 890ddd
		TPixel32 *pix = (TPixel32 *)buffer;
Toshihiro Shimizu 890ddd
		tmp = (unsigned char *)malloc((m_info.m_lx + 1) * 3);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//     unsigned char tmp[10000];
Toshihiro Shimizu 890ddd
		int k = 0;
Toshihiro Shimizu 890ddd
		for (int j = 0; j < m_info.m_lx; j++) {
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//tmp = (pix->r&0xe0)|((pix->g&0xe0)>>3) | ((pix->b&0xc0)>>6);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#if defined(TNZ_MACHINE_CHANNEL_ORDER_MRGB) || defined(TNZ_MACHINE_CHANNEL_ORDER_RGBM)
Toshihiro Shimizu 890ddd
			tmp[k++] = pix->r;
Toshihiro Shimizu 890ddd
			tmp[k++] = pix->g;
Toshihiro Shimizu 890ddd
			tmp[k++] = pix->b;
Toshihiro Shimizu 890ddd
#elif defined(TNZ_MACHINE_CHANNEL_ORDER_MBGR) || defined(TNZ_MACHINE_CHANNEL_ORDER_BGRM)
Toshihiro Shimizu 890ddd
			tmp[k++] = pix->b;
Toshihiro Shimizu 890ddd
			tmp[k++] = pix->g;
Toshihiro Shimizu 890ddd
			tmp[k++] = pix->r;
Toshihiro Shimizu 890ddd
#else
Campbell Barton 42d601
#error		"unknown channel order"
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			++pix;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		png_write_row(m_png_ptr, tmp);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=========================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Tiio::Reader *Tiio::makePngReader()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return new PngReader();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Tiio::Writer *Tiio::makePngWriter()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return new PngWriter();
Toshihiro Shimizu 890ddd
}