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