Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#if _MSC_VER >= 1400
Toshihiro Shimizu 890ddd
#define _CRT_SECURE_NO_DEPRECATE 1
Toshihiro Shimizu 890ddd
#pragma warning(disable : 4996)
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//#include "texception.h"
Toshihiro Shimizu 890ddd
//#include "tfilepath.h"
Toshihiro Shimizu 890ddd
#include "tiio_tga.h"
Toshihiro Shimizu 890ddd
#include "tpixel.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//#include <iostream.h></iostream.h>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
inline unsigned short fgetUSHORT(FILE *chan)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int b0 = fgetc(chan);
Toshihiro Shimizu 890ddd
	int b1 = fgetc(chan);
Toshihiro Shimizu 890ddd
	return b1 << 8 | b0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
inline unsigned short fgetULONG(FILE *chan) 
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
  int a = fgetc(chan);
Toshihiro Shimizu 890ddd
  int b = fgetc(chan);
Toshihiro Shimizu 890ddd
  int c = fgetc(chan);
Toshihiro Shimizu 890ddd
  int d = fgetc(chan);
Toshihiro Shimizu 890ddd
  return a<<24|b<<16|c<<8|d;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
inline void fputUSHORT(unsigned short x, FILE *chan)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int b1 = x >> 8;
Toshihiro Shimizu 890ddd
	int b0 = x & 0xFF;
Toshihiro Shimizu 890ddd
	fputc(b0, chan);
Toshihiro Shimizu 890ddd
	fputc(b1, chan);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
inline void fputULONG(unsigned long x, FILE *chan)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
  int a = x>>24;
Toshihiro Shimizu 890ddd
  int b = (x>>16)&0xff;
Toshihiro Shimizu 890ddd
  int c = (x>>8)&0xff;
Toshihiro Shimizu 890ddd
  int d = x&0xFF;
Toshihiro Shimizu 890ddd
  fputc(a, chan);
Toshihiro Shimizu 890ddd
  fputc(b, chan);
Toshihiro Shimizu 890ddd
  fputc(c, chan);
Toshihiro Shimizu 890ddd
  fputc(d, chan);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
typedef unsigned char UCHAR;
Toshihiro Shimizu 890ddd
typedef unsigned short USHORT;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
struct TgaHeader {
Toshihiro Shimizu 890ddd
	UCHAR IdentificationField;
Toshihiro Shimizu 890ddd
	UCHAR ColorMapType;
Toshihiro Shimizu 890ddd
	UCHAR ImageTypeCode;
Toshihiro Shimizu 890ddd
	USHORT ColorMapOrigin;
Toshihiro Shimizu 890ddd
	USHORT ColorMapLength;
Toshihiro Shimizu 890ddd
	UCHAR ColorMapSize;
Toshihiro Shimizu 890ddd
	USHORT Ximage;
Toshihiro Shimizu 890ddd
	USHORT Yimage;
Toshihiro Shimizu 890ddd
	USHORT Width;
Toshihiro Shimizu 890ddd
	USHORT Height;
Toshihiro Shimizu 890ddd
	UCHAR ImagePixelSize;
Toshihiro Shimizu 890ddd
	UCHAR ImageDescriptor;
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//============================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void readTgaHeader(TgaHeader &header, FILE *chan)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	header.IdentificationField = fgetc(chan);
Toshihiro Shimizu 890ddd
	header.ColorMapType = fgetc(chan);
Toshihiro Shimizu 890ddd
	header.ImageTypeCode = fgetc(chan);
Toshihiro Shimizu 890ddd
	header.ColorMapOrigin = fgetUSHORT(chan);
Toshihiro Shimizu 890ddd
	header.ColorMapLength = fgetUSHORT(chan);
Toshihiro Shimizu 890ddd
	header.ColorMapSize = fgetc(chan);
Toshihiro Shimizu 890ddd
	header.Ximage = fgetUSHORT(chan);
Toshihiro Shimizu 890ddd
	header.Yimage = fgetUSHORT(chan);
Toshihiro Shimizu 890ddd
	header.Width = fgetUSHORT(chan);
Toshihiro Shimizu 890ddd
	header.Height = fgetUSHORT(chan);
Toshihiro Shimizu 890ddd
	header.ImagePixelSize = fgetc(chan);
Toshihiro Shimizu 890ddd
	header.ImageDescriptor = fgetc(chan);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void writeTgaHeader(TgaHeader &header, FILE *chan)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	fputc(header.IdentificationField, chan);
Toshihiro Shimizu 890ddd
	fputc(header.ColorMapType, chan);
Toshihiro Shimizu 890ddd
	fputc(header.ImageTypeCode, chan);
Toshihiro Shimizu 890ddd
	fputUSHORT(header.ColorMapOrigin, chan);
Toshihiro Shimizu 890ddd
	fputUSHORT(header.ColorMapLength, chan);
Toshihiro Shimizu 890ddd
	fputc(header.ColorMapSize, chan);
Toshihiro Shimizu 890ddd
	fputUSHORT(header.Ximage, chan);
Toshihiro Shimizu 890ddd
	fputUSHORT(header.Yimage, chan);
Toshihiro Shimizu 890ddd
	fputUSHORT(header.Width, chan);
Toshihiro Shimizu 890ddd
	fputUSHORT(header.Height, chan);
Toshihiro Shimizu 890ddd
	fputc(header.ImagePixelSize, chan);
Toshihiro Shimizu 890ddd
	fputc(header.ImageDescriptor, chan);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//============================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class TgaReader : public Tiio::Reader
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	FILE *m_chan;
Toshihiro Shimizu 890ddd
	TgaHeader m_header;
Toshihiro Shimizu 890ddd
	TPixel32 *m_palette;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	typedef void (TgaReader::*ReadLineProc)(char *buffer, int x0, int x1, int shrink);
Toshihiro Shimizu 890ddd
	ReadLineProc m_readLineProc;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	typedef int (TgaReader::*SkipLineProc)(int count);
Toshihiro Shimizu 890ddd
	SkipLineProc m_skipLineProc;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	TgaReader()
Toshihiro Shimizu 890ddd
		: m_chan(0), m_readLineProc(&TgaReader::readNoLine), m_skipLineProc(&TgaReader::skipLines0), m_palette(0)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	~TgaReader();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void open(FILE *file);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int skipLines0(int count)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		int lineSize = m_info.m_lx;
Toshihiro Shimizu 890ddd
		fseek(m_chan, count * lineSize, SEEK_CUR);
Toshihiro Shimizu 890ddd
		return count;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	int skipNoLines(int count) { return 0; };
Toshihiro Shimizu 890ddd
	void skipBytes(int count)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		//fseek(m_chan, count, SEEK_CUR); //inefficiente se count รจ piccolo
Toshihiro Shimizu 890ddd
		for (int i = 0; i < count; i++)
Toshihiro Shimizu 890ddd
			getc(m_chan);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int skipLines32(int count)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		skipLines0(4 * count);
Toshihiro Shimizu 890ddd
		return count;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	int skipLines24(int count)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		skipLines0(3 * count);
Toshihiro Shimizu 890ddd
		return count;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	int skipLines16(int count)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		skipLines0(2 * count);
Toshihiro Shimizu 890ddd
		return count;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	inline TPixel32 fgetPixel32(FILE *chan)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		TPixel32 pix;
Toshihiro Shimizu 890ddd
		pix.b = fgetc(chan);
Toshihiro Shimizu 890ddd
		pix.g = fgetc(chan);
Toshihiro Shimizu 890ddd
		pix.r = fgetc(chan);
Toshihiro Shimizu 890ddd
		pix.m = fgetc(chan);
Toshihiro Shimizu 890ddd
		return pix;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	inline TPixel32 fgetPixel24(FILE *chan)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		TPixel32 pix;
Toshihiro Shimizu 890ddd
		pix.b = fgetc(chan);
Toshihiro Shimizu 890ddd
		pix.g = fgetc(chan);
Toshihiro Shimizu 890ddd
		pix.r = fgetc(chan);
Toshihiro Shimizu 890ddd
		pix.m = 255;
Toshihiro Shimizu 890ddd
		return pix;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	inline TPixel32 fgetPixel16(FILE *chan)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		TPixel32 pix;
Toshihiro Shimizu 890ddd
		unsigned short s = fgetUSHORT(chan);
Toshihiro Shimizu 890ddd
		int b = s & 0x1f;
Toshihiro Shimizu 890ddd
		int g = (s >> 5) & 0x1f;
Toshihiro Shimizu 890ddd
		int r = (s >> 10) & 0x1f;
Toshihiro Shimizu 890ddd
		pix.r = r << 3 | r >> 2;
Toshihiro Shimizu 890ddd
		pix.g = g << 3 | g >> 2;
Toshihiro Shimizu 890ddd
		pix.b = b << 3 | b >> 2;
Toshihiro Shimizu 890ddd
		pix.m = 255;
Toshihiro Shimizu 890ddd
		return pix;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	Tiio::RowOrder getRowOrder() const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return ((m_header.ImageDescriptor >> 5) & 1) == 0
Toshihiro Shimizu 890ddd
				   ? Tiio::BOTTOM2TOP
Toshihiro Shimizu 890ddd
				   : Tiio::TOP2BOTTOM;
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
		(this->*m_readLineProc)(buffer, x0, x1, shrink);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	int skipLines(int count)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return (this->*m_skipLineProc)(count);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	void readPalette();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void readNoLine(char *buffer, int x0, int x1, int shrink) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void readLineRGB32(char *buffer, int x0, int x1, int shrink);
Toshihiro Shimizu 890ddd
	void readLineRGB32rle(char *buffer, int x0, int x1, int shrink);
Toshihiro Shimizu 890ddd
	void readLineRGB24(char *buffer, int x0, int x1, int shrink);
Toshihiro Shimizu 890ddd
	void readLineRGB24rle(char *buffer, int x0, int x1, int shrink);
Toshihiro Shimizu 890ddd
	void readLineRGB16(char *buffer, int x0, int x1, int shrink);
Toshihiro Shimizu 890ddd
	void readLineRGB16rle(char *buffer, int x0, int x1, int shrink);
Toshihiro Shimizu 890ddd
	void readLineGR8(char *buffer, int x0, int x1, int shrink);
Toshihiro Shimizu 890ddd
	void readLineGR8rle(char *buffer, int x0, int x1, int shrink);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void readLineCmapped(char *buffer, int x0, int x1, int shrink);
Toshihiro Shimizu 890ddd
	void readLineCmappedRle(char *buffer, int x0, int x1, int shrink);
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TgaReader::~TgaReader()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	delete m_palette;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TgaReader::open(FILE *file)
Toshihiro Shimizu 890ddd
{
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
		readTgaHeader(m_header, m_chan);
Toshihiro Shimizu 890ddd
		m_info.m_lx = m_header.Width;
Toshihiro Shimizu 890ddd
		m_info.m_ly = m_header.Height;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (m_header.IdentificationField > 0) {
Toshihiro Shimizu 890ddd
			char tmp[256];
Toshihiro Shimizu 890ddd
			fread(tmp, 1, m_header.IdentificationField, m_chan);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		if (m_header.ColorMapType > 0) {
Toshihiro Shimizu 890ddd
			readPalette();
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		Tiio::TgaWriterProperties *prop = new Tiio::TgaWriterProperties();
Toshihiro Shimizu 890ddd
		m_info.m_properties = prop;
Toshihiro Shimizu 890ddd
		prop->m_compressed.setValue(false);
Toshihiro Shimizu 890ddd
		switch (m_header.ImageTypeCode) {
Toshihiro Shimizu 890ddd
		case 0:
Toshihiro Shimizu 890ddd
			//cout << "NO IMAGE" << endl;
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
		case 1:
Toshihiro Shimizu 890ddd
			//cout << "Uncompressed Cmapped; pixelsize=" << m_header.ImagePixelSize << endl;
Toshihiro Shimizu 890ddd
			m_readLineProc = &TgaReader::readLineCmapped;
Toshihiro Shimizu 890ddd
			m_info.m_samplePerPixel = 4;
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
		case 2:
Toshihiro Shimizu 890ddd
			//cout << "Uncompressed RGB; pixelsize=" << m_header.ImagePixelSize << endl;
Toshihiro Shimizu 890ddd
			m_info.m_samplePerPixel = 4;
Toshihiro Shimizu 890ddd
			if (m_header.ImagePixelSize == 32) {
Toshihiro Shimizu 890ddd
				m_readLineProc = &TgaReader::readLineRGB32;
Toshihiro Shimizu 890ddd
				m_skipLineProc = &TgaReader::skipLines32;
Toshihiro Shimizu 890ddd
			} else if (m_header.ImagePixelSize == 24) {
Toshihiro Shimizu 890ddd
				m_info.m_samplePerPixel = 3;
Toshihiro Shimizu 890ddd
				m_readLineProc = &TgaReader::readLineRGB24;
Toshihiro Shimizu 890ddd
				m_skipLineProc = &TgaReader::skipLines24;
Toshihiro Shimizu 890ddd
			} else if (m_header.ImagePixelSize == 16) {
Toshihiro Shimizu 890ddd
				m_readLineProc = &TgaReader::readLineRGB16;
Toshihiro Shimizu 890ddd
				m_skipLineProc = &TgaReader::skipLines16;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
		case 3:
Toshihiro Shimizu 890ddd
			m_info.m_samplePerPixel = 1;
Toshihiro Shimizu 890ddd
			m_readLineProc = &TgaReader::readLineGR8;
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
		case 9:
Toshihiro Shimizu 890ddd
			//cout << "Compressed Cmapped; pixelsize=" << m_header.ImagePixelSize << endl;
Toshihiro Shimizu 890ddd
			prop->m_compressed.setValue(true);
Toshihiro Shimizu 890ddd
			m_readLineProc = &TgaReader::readLineCmappedRle;
Toshihiro Shimizu 890ddd
			m_info.m_samplePerPixel = 4;
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
		case 10:
Toshihiro Shimizu 890ddd
			//cout << "Compressed RGB; pixelsize=" << m_header.ImagePixelSize << endl;
Toshihiro Shimizu 890ddd
			prop->m_compressed.setValue(true);
Toshihiro Shimizu 890ddd
			m_info.m_samplePerPixel = 4;
Toshihiro Shimizu 890ddd
			if (m_header.ImagePixelSize == 32) {
Toshihiro Shimizu 890ddd
				m_readLineProc = &TgaReader::readLineRGB32rle;
Toshihiro Shimizu 890ddd
				m_skipLineProc = &TgaReader::skipNoLines;
Toshihiro Shimizu 890ddd
			} else if (m_header.ImagePixelSize == 24) {
Toshihiro Shimizu 890ddd
				m_info.m_samplePerPixel = 3;
Toshihiro Shimizu 890ddd
				m_readLineProc = &TgaReader::readLineRGB24rle;
Toshihiro Shimizu 890ddd
				m_skipLineProc = &TgaReader::skipNoLines;
Toshihiro Shimizu 890ddd
			} else if (m_header.ImagePixelSize == 16) {
Toshihiro Shimizu 890ddd
				m_readLineProc = &TgaReader::readLineRGB16rle;
Toshihiro Shimizu 890ddd
				m_skipLineProc = &TgaReader::skipNoLines;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
		case 11:
Toshihiro Shimizu 890ddd
			m_info.m_samplePerPixel = 1;
Toshihiro Shimizu 890ddd
			m_readLineProc = &TgaReader::readLineGR8rle;
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
		default:;
Toshihiro Shimizu 890ddd
			//cout << "***Unknown***" << endl;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TgaReader::readPalette()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int colorCount = m_header.ColorMapLength;
Toshihiro Shimizu 890ddd
	int bitPerColor = m_header.ColorMapSize;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// cout << "Reading palette: " << colorCount << " " << bitPerColor << "-entries" << endl;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_palette = new TPixel32[colorCount];
Toshihiro Shimizu 890ddd
	int i;
Toshihiro Shimizu 890ddd
	switch (bitPerColor) {
Toshihiro Shimizu 890ddd
	case 16:
Toshihiro Shimizu 890ddd
		for (i = 0; i < colorCount; i++)
Toshihiro Shimizu 890ddd
			m_palette[i] = fgetPixel16(m_chan);
Toshihiro Shimizu 890ddd
		break;
Toshihiro Shimizu 890ddd
	case 24:
Toshihiro Shimizu 890ddd
		for (i = 0; i < colorCount; i++)
Toshihiro Shimizu 890ddd
			m_palette[i] = fgetPixel24(m_chan);
Toshihiro Shimizu 890ddd
		break;
Toshihiro Shimizu 890ddd
	case 32:
Toshihiro Shimizu 890ddd
		for (i = 0; i < colorCount; i++)
Toshihiro Shimizu 890ddd
			m_palette[i] = fgetPixel32(m_chan);
Toshihiro Shimizu 890ddd
		break;
Toshihiro Shimizu 890ddd
		break;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TgaReader::readLineRGB32(char *buffer, int x0, int x1, int shrink)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TPixel32 *pix = (TPixel32 *)buffer;
Toshihiro Shimizu 890ddd
	pix += x0;
Toshihiro Shimizu 890ddd
	if (x0 > 0)
Toshihiro Shimizu 890ddd
		skipBytes(4 * x0);
Toshihiro Shimizu 890ddd
	TPixel32 *endPix = pix + x1 - x0 + 1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	while (pix < endPix) {
Toshihiro Shimizu 890ddd
		*pix++ = fgetPixel32(m_chan);
Toshihiro Shimizu 890ddd
		if (pix < endPix && shrink > 1) {
Toshihiro Shimizu 890ddd
			pix += (shrink - 1);
Toshihiro Shimizu 890ddd
			skipBytes(4 * (shrink - 1));
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	if (m_info.m_lx - x1 - 1 > 0)
Toshihiro Shimizu 890ddd
		skipBytes(4 * (m_info.m_lx - x1 - 1));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TgaReader::readLineRGB24(char *buffer, int x0, int x1, int shrink)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TPixel32 *pix = (TPixel32 *)buffer;
Toshihiro Shimizu 890ddd
	pix += x0;
Toshihiro Shimizu 890ddd
	if (x0 > 0)
Toshihiro Shimizu 890ddd
		skipBytes(3 * x0);
Toshihiro Shimizu 890ddd
	TPixel32 *endPix = pix + x1 - x0 + 1;
Toshihiro Shimizu 890ddd
	while (pix < endPix) {
Toshihiro Shimizu 890ddd
		*pix++ = fgetPixel24(m_chan);
Toshihiro Shimizu 890ddd
		if (pix < endPix && shrink > 1) {
Toshihiro Shimizu 890ddd
			pix += (shrink - 1);
Toshihiro Shimizu 890ddd
			skipBytes(3 * (shrink - 1));
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	if (m_info.m_lx - x1 - 1 > 0)
Toshihiro Shimizu 890ddd
		skipBytes(3 * (m_info.m_lx - x1 - 1));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TgaReader::readLineRGB16(char *buffer, int x0, int x1, int shrink)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TPixel32 *pix = (TPixel32 *)buffer;
Toshihiro Shimizu 890ddd
	pix += x0;
Toshihiro Shimizu 890ddd
	if (x0 > 0)
Toshihiro Shimizu 890ddd
		skipBytes(2 * x0);
Toshihiro Shimizu 890ddd
	TPixel32 *endPix = pix + x1 - x0 + 1;
Toshihiro Shimizu 890ddd
	while (pix < endPix) {
Toshihiro Shimizu 890ddd
		*pix++ = fgetPixel16(m_chan);
Toshihiro Shimizu 890ddd
		if (pix < endPix && shrink > 1) {
Toshihiro Shimizu 890ddd
			pix += (shrink - 1);
Toshihiro Shimizu 890ddd
			skipBytes(2 * (shrink - 1));
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	if (m_info.m_lx - x1 - 1 > 0)
Toshihiro Shimizu 890ddd
		skipBytes(2 * (m_info.m_lx - x1 - 1));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TgaReader::readLineCmapped(char *buffer, int x0, int x1, int shrink)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TPixel32 *pix = (TPixel32 *)buffer;
Toshihiro Shimizu 890ddd
	pix += x0;
Toshihiro Shimizu 890ddd
	if (x0 > 0)
Toshihiro Shimizu 890ddd
		skipBytes(x0);
Toshihiro Shimizu 890ddd
	TPixel32 *endPix = pix + x1 - x0 + 1;
Toshihiro Shimizu 890ddd
	while (pix < endPix) {
Toshihiro Shimizu 890ddd
		int index = fgetc(m_chan);
Toshihiro Shimizu 890ddd
		*pix++ = m_palette[index];
Toshihiro Shimizu 890ddd
		if (pix < endPix && shrink > 1) {
Toshihiro Shimizu 890ddd
			pix += (shrink - 1);
Toshihiro Shimizu 890ddd
			skipBytes(shrink - 1);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	if (m_info.m_lx - x1 - 1 > 0)
Toshihiro Shimizu 890ddd
		skipBytes(m_info.m_lx - x1 - 1);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TgaReader::readLineRGB32rle(char *buffer, int x0, int x1, int shrink)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int x = 0;
Toshihiro Shimizu 890ddd
	TPixel32 *row = (TPixel32 *)buffer;
Toshihiro Shimizu 890ddd
	while (x < m_info.m_lx) {
Toshihiro Shimizu 890ddd
		UCHAR h = fgetc(m_chan);
Toshihiro Shimizu 890ddd
		int count = (h & 0x7F) + 1;
Toshihiro Shimizu 890ddd
		if (h & 0x80) {
Toshihiro Shimizu 890ddd
			TPixel32 pix = fgetPixel32(m_chan);
Toshihiro Shimizu 890ddd
			for (int i = 0; i < count && x < m_info.m_lx; i++)
Toshihiro Shimizu 890ddd
				row[x++] = pix;
Toshihiro Shimizu 890ddd
		} else
Toshihiro Shimizu 890ddd
			for (int i = 0; i < count && x < m_info.m_lx; i++)
Toshihiro Shimizu 890ddd
				row[x++] = fgetPixel32(m_chan);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TgaReader::readLineRGB24rle(char *buffer, int x0, int x1, int shrink)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int x = 0;
Toshihiro Shimizu 890ddd
	TPixel32 *row = (TPixel32 *)buffer;
Toshihiro Shimizu 890ddd
	while (x < m_info.m_lx) {
Toshihiro Shimizu 890ddd
		UCHAR h = fgetc(m_chan);
Toshihiro Shimizu 890ddd
		int count = (h & 0x7F) + 1;
Toshihiro Shimizu 890ddd
		if (h & 0x80) {
Toshihiro Shimizu 890ddd
			TPixel32 pix = fgetPixel24(m_chan);
Toshihiro Shimizu 890ddd
			for (int i = 0; i < count && x < m_info.m_lx; i++)
Toshihiro Shimizu 890ddd
				row[x++] = pix;
Toshihiro Shimizu 890ddd
		} else
Toshihiro Shimizu 890ddd
			for (int i = 0; i < count && x < m_info.m_lx; i++)
Toshihiro Shimizu 890ddd
				row[x++] = fgetPixel24(m_chan);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TgaReader::readLineRGB16rle(char *buffer, int x0, int x1, int shrink)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int x = 0;
Toshihiro Shimizu 890ddd
	TPixel32 *row = (TPixel32 *)buffer;
Toshihiro Shimizu 890ddd
	while (x < m_info.m_lx) {
Toshihiro Shimizu 890ddd
		UCHAR h = fgetc(m_chan);
Toshihiro Shimizu 890ddd
		int count = (h & 0x7F) + 1;
Toshihiro Shimizu 890ddd
		if (h & 0x80) {
Toshihiro Shimizu 890ddd
			TPixel32 pix = fgetPixel16(m_chan);
Toshihiro Shimizu 890ddd
			for (int i = 0; i < count && x < m_info.m_lx; i++)
Toshihiro Shimizu 890ddd
				row[x++] = pix;
Toshihiro Shimizu 890ddd
		} else
Toshihiro Shimizu 890ddd
			for (int i = 0; i < count && x < m_info.m_lx; i++)
Toshihiro Shimizu 890ddd
				row[x++] = fgetPixel16(m_chan);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TgaReader::readLineGR8(char *buffer, int x0, int x1, int shrink)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TPixel32 *row = (TPixel32 *)buffer;
Toshihiro Shimizu 890ddd
	int w = x1 - x0 + 1;
Toshihiro Shimizu 890ddd
	while (w--) {
Toshihiro Shimizu 890ddd
		row->r = row->g = row->b = fgetc(m_chan);
Toshihiro Shimizu 890ddd
		row->m = 0xff;
Toshihiro Shimizu 890ddd
		++row;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TgaReader::readLineGR8rle(char *buffer, int x0, int x1, int shrink)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TPixel32 *row = (TPixel32 *)buffer;
Toshihiro Shimizu 890ddd
	UCHAR count, byte;
Toshihiro Shimizu 890ddd
	int nx, x, i;
Toshihiro Shimizu 890ddd
	int width = x1 - x0 + 1;
Toshihiro Shimizu 890ddd
	for (nx = 0; nx < width;) {
Toshihiro Shimizu 890ddd
		count = fgetc(m_chan);
Toshihiro Shimizu 890ddd
		if ((count >> 7) & 0x01) {
Toshihiro Shimizu 890ddd
			count -= 127;
Toshihiro Shimizu 890ddd
			byte = fgetc(m_chan);
Toshihiro Shimizu 890ddd
			for (x = 0; x < count; x++) {
Toshihiro Shimizu 890ddd
				row->r = row->g = row->b = byte;
Toshihiro Shimizu 890ddd
				row->m = 0xff;
Toshihiro Shimizu 890ddd
				++row;
Toshihiro Shimizu 890ddd
				nx++;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			for (i = 0; i < count + 1; i++) {
Toshihiro Shimizu 890ddd
				byte = fgetc(m_chan);
Toshihiro Shimizu 890ddd
				row->r = row->g = row->b = byte;
Toshihiro Shimizu 890ddd
				row->m = 0xff;
Toshihiro Shimizu 890ddd
				++row;
Toshihiro Shimizu 890ddd
				nx++;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	if (nx != width)
Toshihiro Shimizu 890ddd
		fprintf(stderr, "tga read error: decode failed\n");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TgaReader::readLineCmappedRle(char *buffer, int x0, int x1, int shrink)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int x = 0;
Toshihiro Shimizu 890ddd
	TPixel32 *row = (TPixel32 *)buffer;
Toshihiro Shimizu 890ddd
	while (x < m_info.m_lx) {
Toshihiro Shimizu 890ddd
		UCHAR h = fgetc(m_chan);
Toshihiro Shimizu 890ddd
		int count = (h & 0x7F) + 1;
Toshihiro Shimizu 890ddd
		if (h & 0x80) {
Toshihiro Shimizu 890ddd
			int index = fgetc(m_chan);
Toshihiro Shimizu 890ddd
			TPixel32 pix = m_palette[index];
Toshihiro Shimizu 890ddd
			for (int i = 0; i < count && x < m_info.m_lx; i++)
Toshihiro Shimizu 890ddd
				row[x++] = pix;
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			for (int i = 0; i < count && x < m_info.m_lx; i++) {
Toshihiro Shimizu 890ddd
				int index = fgetc(m_chan);
Toshihiro Shimizu 890ddd
				row[x++] = m_palette[index];
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//============================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Tiio::TgaWriterProperties::TgaWriterProperties()
Toshihiro Shimizu 890ddd
	: m_pixelSize("Bits Per Pixel"), m_compressed("Compression", true)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_pixelSize.addValue(L"16 bits");
Toshihiro Shimizu 890ddd
	m_pixelSize.addValue(L"24 bits");
Toshihiro Shimizu 890ddd
	m_pixelSize.addValue(L"32 bits");
Toshihiro Shimizu 890ddd
	m_pixelSize.setValue(L"24 bits");
Toshihiro Shimizu 890ddd
	bind(m_pixelSize);
Toshihiro Shimizu 890ddd
	bind(m_compressed);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//============================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class TgaWriter : public Tiio::Writer
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	FILE *m_chan;
Toshihiro Shimizu 890ddd
	TgaHeader m_header;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	typedef void (TgaWriter::*WriteLineProc)(char *buffer);
Toshihiro Shimizu 890ddd
	WriteLineProc m_writeLineProc;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	TgaWriter()
Toshihiro Shimizu 890ddd
		: m_chan(0), m_writeLineProc(&TgaWriter::writeNoLine)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void open(FILE *file, const TImageInfo &info)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		m_info = info;
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
		if (!m_properties)
Toshihiro Shimizu 890ddd
			m_properties = new Tiio::TgaWriterProperties();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		bool compressed = ((TBoolProperty *)(m_properties->getProperty("Compression")))->getValue();
Toshihiro Shimizu 890ddd
		memset(&m_header, 0, sizeof(m_header));
Toshihiro Shimizu 890ddd
		m_header.ImageTypeCode = compressed ? 10 : 2;
Toshihiro Shimizu 890ddd
		m_header.Width = m_info.m_lx;
Toshihiro Shimizu 890ddd
		m_header.Height = m_info.m_ly;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		wstring pixelSizeW = ((TEnumProperty *)(m_properties->getProperty("Bits Per Pixel")))->getValue().substr(0, 2);
Toshihiro Shimizu 890ddd
		if (pixelSizeW == L"16") {
Toshihiro Shimizu 890ddd
			m_header.ImagePixelSize = 16;
Toshihiro Shimizu 890ddd
			m_writeLineProc = compressed
Toshihiro Shimizu 890ddd
								  ? &TgaWriter::writeLine16rle
Toshihiro Shimizu 890ddd
								  : &TgaWriter::writeLine16;
Toshihiro Shimizu 890ddd
		} else if (pixelSizeW == L"24") {
Toshihiro Shimizu 890ddd
			m_header.ImagePixelSize = 24;
Toshihiro Shimizu 890ddd
			m_writeLineProc = compressed
Toshihiro Shimizu 890ddd
								  ? &TgaWriter::writeLine24rle
Toshihiro Shimizu 890ddd
								  : &TgaWriter::writeLine24;
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			m_header.ImagePixelSize = 32;
Toshihiro Shimizu 890ddd
			m_writeLineProc = compressed
Toshihiro Shimizu 890ddd
								  ? &TgaWriter::writeLine32rle
Toshihiro Shimizu 890ddd
								  : &TgaWriter::writeLine32;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		writeTgaHeader(m_header, m_chan);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void flush()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		fflush(m_chan);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	~TgaWriter()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		delete m_properties;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	inline void fputPixel32(const TPixel32 &pix, FILE *chan)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		fputc(pix.b, m_chan);
Toshihiro Shimizu 890ddd
		fputc(pix.g, m_chan);
Toshihiro Shimizu 890ddd
		fputc(pix.r, m_chan);
Toshihiro Shimizu 890ddd
		fputc(pix.m, m_chan);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	inline void fputPixel24(const TPixel32 &pix, FILE *chan)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		fputc(pix.b, m_chan);
Toshihiro Shimizu 890ddd
		fputc(pix.g, m_chan);
Toshihiro Shimizu 890ddd
		fputc(pix.r, m_chan);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	inline void fputPixel16(const TPixel32 &pix, FILE *chan)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		unsigned short word;
Toshihiro Shimizu 890ddd
		word = (pix.r >> 3) << 10 | (pix.g >> 3) << 5 | (pix.b >> 3);
Toshihiro Shimizu 890ddd
		fputc(word & 0xFF, m_chan);
Toshihiro Shimizu 890ddd
		fputc((word >> 8) & 0xFF, m_chan);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void writeNoLine(char *buffer) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void writeLine16(char *buffer);
Toshihiro Shimizu 890ddd
	void writeLine24(char *buffer);
Toshihiro Shimizu 890ddd
	void writeLine32(char *buffer);
Toshihiro Shimizu 890ddd
	void writeLine16rle(char *buffer);
Toshihiro Shimizu 890ddd
	void writeLine24rle(char *buffer);
Toshihiro Shimizu 890ddd
	void writeLine32rle(char *buffer);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void writeLine(char *buffer)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		(this->*m_writeLineProc)(buffer);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TgaWriter::writeLine32rle(char *buffer)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int x = 0;
Toshihiro Shimizu 890ddd
	TPixel32 *row = (TPixel32 *)buffer;
Toshihiro Shimizu 890ddd
	while (x < m_info.m_lx) {
Toshihiro Shimizu 890ddd
		if (x + 1 < m_info.m_lx && row[x] == row[x + 1]) {
Toshihiro Shimizu 890ddd
			int count = 2;
Toshihiro Shimizu 890ddd
			int max = tmin(128, m_info.m_lx - x);
Toshihiro Shimizu 890ddd
			while (count < max && row[x + count - 1] == row[x + count])
Toshihiro Shimizu 890ddd
				count++;
Toshihiro Shimizu 890ddd
			fputc((count - 1) | 0x80, m_chan);
Toshihiro Shimizu 890ddd
			fputPixel32(row[x], m_chan);
Toshihiro Shimizu 890ddd
			x += count;
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			int count = 1;
Toshihiro Shimizu 890ddd
			int max = tmin(128, m_info.m_lx - x);
Toshihiro Shimizu 890ddd
			while (count < max && row[x + count - 1] != row[x + count])
Toshihiro Shimizu 890ddd
				count++;
Toshihiro Shimizu 890ddd
			fputc(count - 1, m_chan);
Toshihiro Shimizu 890ddd
			for (int i = 0; i < count; i++)
Toshihiro Shimizu 890ddd
				fputPixel32(row[x++], m_chan);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TgaWriter::writeLine24rle(char *buffer)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int x = 0;
Toshihiro Shimizu 890ddd
	TPixel32 *row = (TPixel32 *)buffer;
Toshihiro Shimizu 890ddd
	while (x < m_info.m_lx) {
Toshihiro Shimizu 890ddd
		if (x + 1 < m_info.m_lx && row[x] == row[x + 1]) {
Toshihiro Shimizu 890ddd
			int count = 2;
Toshihiro Shimizu 890ddd
			int max = tmin(128, m_info.m_lx - x);
Toshihiro Shimizu 890ddd
			while (count < max && row[x + count - 1] == row[x + count])
Toshihiro Shimizu 890ddd
				count++;
Toshihiro Shimizu 890ddd
			fputc((count - 1) | 0x80, m_chan);
Toshihiro Shimizu 890ddd
			fputPixel24(row[x], m_chan);
Toshihiro Shimizu 890ddd
			x += count;
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			int count = 1;
Toshihiro Shimizu 890ddd
			int max = tmin(128, m_info.m_lx - x);
Toshihiro Shimizu 890ddd
			while (count < max && row[x + count - 1] != row[x + count])
Toshihiro Shimizu 890ddd
				count++;
Toshihiro Shimizu 890ddd
			fputc(count - 1, m_chan);
Toshihiro Shimizu 890ddd
			for (int i = 0; i < count; i++)
Toshihiro Shimizu 890ddd
				fputPixel24(row[x++], m_chan);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TgaWriter::writeLine16rle(char *buffer)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int x = 0;
Toshihiro Shimizu 890ddd
	TPixel32 *row = (TPixel32 *)buffer;
Toshihiro Shimizu 890ddd
	while (x < m_info.m_lx) {
Toshihiro Shimizu 890ddd
		if (x + 1 < m_info.m_lx && row[x] == row[x + 1]) {
Toshihiro Shimizu 890ddd
			int count = 2;
Toshihiro Shimizu 890ddd
			int max = tmin(128, m_info.m_lx - x);
Toshihiro Shimizu 890ddd
			while (count < max && row[x + count - 1] == row[x + count])
Toshihiro Shimizu 890ddd
				count++;
Toshihiro Shimizu 890ddd
			fputc((count - 1) | 0x80, m_chan);
Toshihiro Shimizu 890ddd
			fputPixel16(row[x], m_chan);
Toshihiro Shimizu 890ddd
			x += count;
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			int count = 1;
Toshihiro Shimizu 890ddd
			int max = tmin(128, m_info.m_lx - x);
Toshihiro Shimizu 890ddd
			while (count < max && row[x + count - 1] != row[x + count])
Toshihiro Shimizu 890ddd
				count++;
Toshihiro Shimizu 890ddd
			fputc(count - 1, m_chan);
Toshihiro Shimizu 890ddd
			for (int i = 0; i < count; i++)
Toshihiro Shimizu 890ddd
				fputPixel16(row[x++], m_chan);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TgaWriter::writeLine32(char *buffer)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TPixel32 *pix = (TPixel32 *)buffer;
Toshihiro Shimizu 890ddd
	TPixel32 *endPix = pix + m_info.m_lx;
Toshihiro Shimizu 890ddd
	while (pix < endPix)
Toshihiro Shimizu 890ddd
		fputPixel32(*pix++, m_chan);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TgaWriter::writeLine24(char *buffer)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TPixel32 *pix = (TPixel32 *)buffer;
Toshihiro Shimizu 890ddd
	TPixel32 *endPix = pix + m_info.m_lx;
Toshihiro Shimizu 890ddd
	while (pix < endPix)
Toshihiro Shimizu 890ddd
		fputPixel24(*pix++, m_chan);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TgaWriter::writeLine16(char *buffer)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TPixel32 *pix = (TPixel32 *)buffer;
Toshihiro Shimizu 890ddd
	TPixel32 *endPix = pix + m_info.m_lx;
Toshihiro Shimizu 890ddd
	while (pix < endPix)
Toshihiro Shimizu 890ddd
		fputPixel16(*pix++, m_chan);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//============================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Tiio::Reader *Tiio::makeTgaReader()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return new TgaReader();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Tiio::Writer *Tiio::makeTgaWriter()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return new TgaWriter();
Toshihiro Shimizu 890ddd
}