Campbell Barton d869b5
#if defined(_MSC_VER) && (_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"
shun-iwasawa e6b124
#include "tpixelutils.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
using namespace std;
Toshihiro Shimizu 890ddd
//------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
extern "C" {
fukasawa 13abb6
Campbell Barton 8c6c57
static void tnz_abort(jmp_buf, int) {}
fukasawa 13abb6
Campbell Barton 8c6c57
static void tnz_error_fun(png_structp pngPtr, png_const_charp error_message) {
Shinya Kitaoka 120a6e
  *(int *)png_get_error_ptr(pngPtr) = 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#if !defined(TNZ_LITTLE_ENDIAN)
Michał Janiszewski 01e73f
#error "TNZ_LITTLE_ENDIAN undefined !!"
Michał Janiszewski 01e73f
#endif
Michał Janiszewski 01e73f
Michał Janiszewski 01e73f
//=========================================================
Michał Janiszewski 01e73f
/* Check for the older version of libpng */
Michał Janiszewski 01e73f
Michał Janiszewski 01e73f
#if defined(PNG_LIBPNG_VER)
Michał Janiszewski 01e73f
#if (PNG_LIBPNG_VER < 10527)
Michał Janiszewski 01e73f
extern "C" {
Shinya Kitaoka 2a7129
static png_uint_32 png_get_current_row_number(const png_structp png_ptr) {
Shinya Kitaoka 2a7129
  /* See the comments in png.h - this is the sub-image row when reading and
Shinya Kitaoka 2a7129
   * interlaced image.
Shinya Kitaoka 2a7129
   */
Shinya Kitaoka 2a7129
  if (png_ptr != NULL) return png_ptr->row_number;
Shinya Kitaoka 2a7129
Shinya Kitaoka 2a7129
  return PNG_UINT_32_MAX; /* help the app not to fail silently */
Michał Janiszewski 01e73f
}
Michał Janiszewski 01e73f
Shinya Kitaoka 2a7129
static png_byte png_get_current_pass_number(const png_structp png_ptr) {
Shinya Kitaoka 2a7129
  if (png_ptr != NULL) return png_ptr->pass;
Shinya Kitaoka 2a7129
  return 8; /* invalid */
Michał Janiszewski 01e73f
}
Michał Janiszewski 01e73f
}
Michał Janiszewski 01e73f
#endif
Michał Janiszewski 01e73f
#else
Michał Janiszewski 01e73f
#error "PNG_LIBPNG_VER undefined, libpng too old?"
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Shinya Kitaoka 2a7129
//=========================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 2a7129
inline USHORT mySwap(USHORT val) {
Toshihiro Shimizu 890ddd
#if TNZ_LITTLE_ENDIAN
Shinya Kitaoka 120a6e
  return ((val) |
Shinya Kitaoka 120a6e
          ((val & 0xff) << 8));  //((val>>8)|((val&0xff)<<8)); (vecchio codice)
Toshihiro Shimizu 890ddd
#else
Shinya Kitaoka 120a6e
  return val;
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=========================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class PngReader final : public Tiio::Reader {
Shinya Kitaoka 120a6e
  FILE *m_chan;
Shinya Kitaoka 120a6e
  png_structp m_png_ptr;
Shinya Kitaoka 120a6e
  png_infop m_info_ptr, m_end_info_ptr;
Shinya Kitaoka 120a6e
  int m_bit_depth, m_color_type, m_interlace_type;
Shinya Kitaoka 120a6e
  int m_compression_type, m_filter_type;
Shinya Kitaoka 120a6e
  unsigned int m_sig_read;
Shinya Kitaoka 120a6e
  int m_y;
Shinya Kitaoka 120a6e
  bool m_is16bitEnabled;
Shinya Kitaoka 120a6e
  std::unique_ptr<unsigned char[]=""> m_rowBuffer;</unsigned>
Shinya Kitaoka 120a6e
  std::unique_ptr<unsigned char[]=""> m_tempBuffer;  // Buffer temporaneo</unsigned>
Shinya Kitaoka 120a6e
  int m_canDelete;
Shinya Kitaoka 120a6e
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  PngReader()
Shinya Kitaoka 120a6e
      : m_chan(0)
Shinya Kitaoka 120a6e
      , m_png_ptr(0)
Shinya Kitaoka 120a6e
      , m_info_ptr(0)
Shinya Kitaoka 120a6e
      , m_end_info_ptr(0)
Shinya Kitaoka 120a6e
      , m_bit_depth(0)
Shinya Kitaoka 120a6e
      , m_color_type(0)
Shinya Kitaoka 120a6e
      , m_interlace_type(0)
Shinya Kitaoka 120a6e
      , m_compression_type(0)
Shinya Kitaoka 120a6e
      , m_filter_type(0)
Shinya Kitaoka 120a6e
      , m_sig_read(0)
Shinya Kitaoka 120a6e
      , m_y(0)
Shinya Kitaoka 120a6e
      , m_is16bitEnabled(true)
Shinya Kitaoka 120a6e
      , m_canDelete(0) {}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  ~PngReader() {
Shinya Kitaoka 120a6e
    if (m_canDelete == 1) {
Shinya Kitaoka 120a6e
      png_destroy_read_struct(&m_png_ptr, &m_info_ptr, &m_end_info_ptr);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  bool read16BitIsEnabled() const override { return m_is16bitEnabled; }
Shinya Kitaoka 473e70
Shinya Kitaoka 473e70
  void enable16BitRead(bool enabled) override { m_is16bitEnabled = enabled; }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  void readLineInterlace(char *buffer) {
Shinya Kitaoka 120a6e
    readLineInterlace(buffer, 0, m_info.m_lx - 1, 1);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  void readLineInterlace(short *buffer) {
Shinya Kitaoka 120a6e
    readLineInterlace(buffer, 0, m_info.m_lx - 1, 1);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  void open(FILE *file) override {
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
Shinya Kitaoka 120a6e
    unsigned char signature[8];  // da 1 a 8 bytes
Shinya Kitaoka 120a6e
    fread(signature, 1, sizeof signature, m_chan);
Shinya Kitaoka 120a6e
    bool isPng = !png_sig_cmp(signature, 0, sizeof signature);
Shinya Kitaoka 120a6e
    if (!isPng) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    m_png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, &m_canDelete,
Shinya Kitaoka 120a6e
                                       tnz_error_fun, 0);
Shinya Kitaoka 120a6e
    if (!m_png_ptr) return;
Shinya Kitaoka 120a6e
Michał Janiszewski 01e73f
#if defined(PNG_LIBPNG_VER)
Michał Janiszewski 01e73f
#if (PNG_LIBPNG_VER >= 10527)
Shinya Kitaoka 120a6e
    png_set_longjmp_fn(m_png_ptr, tnz_abort,
Shinya Kitaoka 120a6e
                       sizeof(jmp_buf)); /* ignore all fatal errors */
Shinya Kitaoka 2a7129
#endif                                   // (PNG_LIBPNG_VER >= 10527)
Shinya Kitaoka 2a7129
#endif                                   // defined(PNG_LIBPNG_VER)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    m_canDelete = 1;
Shinya Kitaoka 120a6e
    m_info_ptr  = png_create_info_struct(m_png_ptr);
Shinya Kitaoka 120a6e
    if (!m_info_ptr) {
Shinya Kitaoka 120a6e
      png_destroy_read_struct(&m_png_ptr, (png_infopp)0, (png_infopp)0);
Shinya Kitaoka 120a6e
      return;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    m_end_info_ptr = png_create_info_struct(m_png_ptr);
Shinya Kitaoka 120a6e
    if (!m_end_info_ptr) {
Shinya Kitaoka 120a6e
      png_destroy_read_struct(&m_png_ptr, &m_info_ptr, (png_infopp)0);
Shinya Kitaoka 120a6e
      return;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    png_init_io(m_png_ptr, m_chan);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    png_set_sig_bytes(m_png_ptr, sizeof signature);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#if defined(TNZ_MACHINE_CHANNEL_ORDER_MBGR)
Shinya Kitaoka 120a6e
    png_set_bgr(m_png_ptr);
Shinya Kitaoka 120a6e
    png_set_swap_alpha(m_png_ptr);
Toshihiro Shimizu 890ddd
#elif defined(TNZ_MACHINE_CHANNEL_ORDER_BGRM)
Shinya Kitaoka 120a6e
    png_set_bgr(m_png_ptr);
Toshihiro Shimizu 890ddd
#elif defined(TNZ_MACHINE_CHANNEL_ORDER_MRGB)
Shinya Kitaoka 120a6e
    png_set_swap_alpha(m_png_ptr);
Toshihiro Shimizu 890ddd
#elif !defined(TNZ_MACHINE_CHANNEL_ORDER_RGBM)
Shinya Kitaoka 120a6e
#error "unknown channel order"
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    png_read_info(m_png_ptr, m_info_ptr);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (png_get_valid(m_png_ptr, m_info_ptr, PNG_INFO_pHYs)) {
Shinya Kitaoka 120a6e
      png_uint_32 xdpi = png_get_x_pixels_per_meter(m_png_ptr, m_info_ptr);
Shinya Kitaoka 120a6e
      png_uint_32 ydpi = png_get_y_pixels_per_meter(m_png_ptr, m_info_ptr);
Shinya Kitaoka 120a6e
      m_info.m_dpix    = tround(xdpi * 0.0254);
Shinya Kitaoka 120a6e
      m_info.m_dpiy    = tround(ydpi * 0.0254);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    int rowBytes = png_get_rowbytes(m_png_ptr, m_info_ptr);
Shinya Kitaoka 120a6e
Michał Janiszewski 01e73f
    png_uint_32 lx = 0, ly = 0;
Shinya Kitaoka 120a6e
    png_get_IHDR(m_png_ptr, m_info_ptr, &lx, &ly, &m_bit_depth, &m_color_type,
Shinya Kitaoka 120a6e
                 &m_interlace_type, &m_compression_type, &m_filter_type);
Shinya Kitaoka 120a6e
    m_info.m_lx = lx;
Shinya Kitaoka 120a6e
    m_info.m_ly = ly;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    m_info.m_bitsPerSample = m_bit_depth;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    int channels            = png_get_channels(m_png_ptr, m_info_ptr);
Shinya Kitaoka 120a6e
    m_info.m_samplePerPixel = channels;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (channels == 1 || channels == 2) {
Shinya Kitaoka 120a6e
      if (m_bit_depth <
Shinya Kitaoka 120a6e
          8)  // (m_bit_depth == 1 || m_bit_depth == 2 || m_bit_depth == 4)
Shinya Kitaoka 120a6e
        m_rowBuffer.reset(new unsigned char[lx * 3]);
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        m_rowBuffer.reset(new unsigned char[rowBytes * 4]);
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      m_rowBuffer.reset(new unsigned char[rowBytes]);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (m_color_type == PNG_COLOR_TYPE_PALETTE) {
Shinya Kitaoka 120a6e
      m_info.m_valid = true;
Shinya Kitaoka 120a6e
      png_set_palette_to_rgb(m_png_ptr);
Martin van Zijl 9d02b2
Martin van Zijl 9d02b2
      // treat the image as RGBA from now on
shun-iwasawa 8b6d1f
      m_info.m_samplePerPixel =
shun-iwasawa 8b6d1f
          4;  // there are 4 channels per pixel (R, G, B, and A)
Martin van Zijl 9d02b2
Martin van Zijl 9d02b2
      // if there is no alpha channel, then fill it with "255" (full opacity)
Martin van Zijl 9d02b2
      png_set_filler(m_png_ptr, 0xFF, PNG_FILLER_AFTER);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (m_color_type == PNG_COLOR_TYPE_GRAY && m_bit_depth < 8) {
Shinya Kitaoka 120a6e
      png_set_expand_gray_1_2_4_to_8(m_png_ptr);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (png_get_valid(m_png_ptr, m_info_ptr, PNG_INFO_tRNS)) {
Shinya Kitaoka 120a6e
      png_set_tRNS_to_alpha(m_png_ptr);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (m_bit_depth == 16 && !m_is16bitEnabled) {
Shinya Kitaoka 120a6e
      png_set_strip_16(m_png_ptr);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Toshihiro Shimizu 890ddd
#if defined(TNZ_MACHINE_CHANNEL_ORDER_BGRM)
Shinya Kitaoka 120a6e
    if (m_color_type == PNG_COLOR_TYPE_RGB ||
Shinya Kitaoka 120a6e
        m_color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
Shinya Kitaoka 120a6e
      png_set_bgr(m_png_ptr);
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
#elif defined(TNZ_MACHINE_CHANNEL_ORDER_MBGR)
Shinya Kitaoka 120a6e
    if (m_color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
Shinya Kitaoka 120a6e
      png_set_swap_alpha(m_png_ptr);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
#elif !defined(TNZ_MACHINE_CHANNEL_ORDER_RGBM) &&                              \
Shinya Kitaoka 120a6e
    !defined(TNZ_MACHINE_CHANNEL_ORDER_MRGB)
Shinya Kitaoka 120a6e
#error "unknown channel order"
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if (m_color_type == PNG_COLOR_TYPE_GRAY ||
Shinya Kitaoka 120a6e
        m_color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
Shinya Kitaoka 120a6e
      png_set_gray_to_rgb(m_png_ptr);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  void readLine(char *buffer, int x0, int x1, int shrink) override {
Shinya Kitaoka 120a6e
    int ly = m_info.m_ly;
Shinya Kitaoka 120a6e
    if (!m_tempBuffer) {
Shinya Kitaoka 120a6e
      int lx       = m_info.m_lx;
Shinya Kitaoka 120a6e
      int channels = png_get_channels(m_png_ptr, m_info_ptr);
Shinya Kitaoka 120a6e
      int rowBytes = png_get_rowbytes(m_png_ptr, m_info_ptr);
Shinya Kitaoka 120a6e
      if (m_interlace_type == 1) {
Shinya Kitaoka 120a6e
        if (channels == 1 || channels == 2) {
Shinya Kitaoka 120a6e
          if (m_bit_depth < 8)
Shinya Kitaoka 120a6e
            m_tempBuffer.reset(new unsigned char[ly * lx * 3]);
Shinya Kitaoka 120a6e
          else
Shinya Kitaoka 120a6e
            m_tempBuffer.reset(new unsigned char[ly * rowBytes * 4]);
Shinya Kitaoka 120a6e
        } else {
Shinya Kitaoka 120a6e
          m_tempBuffer.reset(new unsigned char[ly * rowBytes]);
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    int lx = m_info.m_lx;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (m_interlace_type == 1 && lx > 4) {
Shinya Kitaoka 120a6e
      readLineInterlace(&buffer[0], x0, x1, shrink);
Shinya Kitaoka 120a6e
      m_y++;
Shinya Kitaoka 120a6e
      if (m_tempBuffer && m_y == ly) {
Shinya Kitaoka 120a6e
        m_tempBuffer.reset();
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      return;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    int y = m_info.m_ly - 1 - m_y;
Shinya Kitaoka 120a6e
    if (y < 0) return;
Shinya Kitaoka 120a6e
    m_y++;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    png_bytep row_pointer = m_rowBuffer.get();
Shinya Kitaoka 120a6e
    png_read_row(m_png_ptr, row_pointer, NULL);
Shinya Kitaoka 120a6e
shun-iwasawa cf34ed
    writeRow(buffer, x0, x1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (m_tempBuffer && m_y == ly) {
Shinya Kitaoka 120a6e
      m_tempBuffer.reset();
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  void readLine(short *buffer, int x0, int x1, int shrink) override {
Shinya Kitaoka 120a6e
    int ly = m_info.m_ly;
Shinya Kitaoka 120a6e
    if (!m_tempBuffer) {
Shinya Kitaoka 120a6e
      int lx       = m_info.m_lx;
Shinya Kitaoka 120a6e
      int channels = png_get_channels(m_png_ptr, m_info_ptr);
Shinya Kitaoka 120a6e
      int rowBytes = png_get_rowbytes(m_png_ptr, m_info_ptr);
Shinya Kitaoka 120a6e
      if (m_interlace_type == 1) {
Shinya Kitaoka 120a6e
        if (channels == 1 || channels == 2) {
Shinya Kitaoka 120a6e
          if (m_bit_depth <
Shinya Kitaoka 120a6e
              8)  // (m_bit_depth == 1 || m_bit_depth == 2 || m_bit_depth == 4)
Shinya Kitaoka 120a6e
            m_tempBuffer.reset(new unsigned char[ly * lx * 3]);
Shinya Kitaoka 120a6e
          else
Shinya Kitaoka 120a6e
            m_tempBuffer.reset(new unsigned char[ly * rowBytes * 4]);
Shinya Kitaoka 120a6e
        } else {
Shinya Kitaoka 120a6e
          m_tempBuffer.reset(new unsigned char[ly * rowBytes]);
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (png_get_interlace_type(m_png_ptr, m_info_ptr) == PNG_INTERLACE_ADAM7) {
Shinya Kitaoka 120a6e
      readLineInterlace(&buffer[0], x0, x1, shrink);
Shinya Kitaoka 120a6e
      m_y++;
Shinya Kitaoka 120a6e
      if (m_tempBuffer && m_y == ly) {
Shinya Kitaoka 120a6e
        m_tempBuffer.reset();
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      return;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    int y = m_info.m_ly - 1 - m_y;
Shinya Kitaoka 120a6e
    if (y < 0) return;
Shinya Kitaoka 120a6e
    m_y++;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    png_bytep row_pointer = m_rowBuffer.get();
Shinya Kitaoka 120a6e
    png_read_row(m_png_ptr, row_pointer, NULL);
Shinya Kitaoka 120a6e
shun-iwasawa cf34ed
    writeRow(buffer, x0, x1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (m_tempBuffer && m_y == ly) {
Shinya Kitaoka 120a6e
      m_tempBuffer.reset();
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  int skipLines(int lineCount) override {
Shinya Kitaoka 120a6e
    for (int i = 0; i < lineCount; i++) {
Shinya Kitaoka 120a6e
      if (m_interlace_type == 1 &&
Shinya Kitaoka 120a6e
          m_info.m_lx > 4)  // pezza. Studiare il codice
Shinya Kitaoka 120a6e
      {
Shinya Kitaoka 120a6e
        int channels     = png_get_channels(m_png_ptr, m_info_ptr);
Shinya Kitaoka 120a6e
        char *lineBuffer = (char *)malloc(4 * m_info.m_lx * sizeof(char));
Shinya Kitaoka 120a6e
        readLine(lineBuffer, 0, m_info.m_lx - 1, 1);
Shinya Kitaoka 120a6e
        free(lineBuffer);
Shinya Kitaoka 120a6e
      } else {
Shinya Kitaoka 120a6e
        m_y++;
Shinya Kitaoka 120a6e
        png_bytep row_pointer = m_rowBuffer.get();
Shinya Kitaoka 120a6e
        png_read_row(m_png_ptr, row_pointer, NULL);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    return lineCount;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  Tiio::RowOrder getRowOrder() const override { return Tiio::TOP2BOTTOM; }
Shinya Kitaoka 120a6e
shun-iwasawa cf34ed
  void writeRow(char *buffer, int x0, int x1) {
Shinya Kitaoka 120a6e
    if (m_color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
Martin van Zijl 9d02b2
        m_color_type == PNG_COLOR_TYPE_GRAY_ALPHA ||
shun-iwasawa 8b6d1f
        m_color_type == PNG_COLOR_TYPE_PALETTE) {  // PNG_COLOR_TYPE_PALETTE is
shun-iwasawa 8b6d1f
                                                   // expanded to RGBA
Shinya Kitaoka 120a6e
      if (m_bit_depth == 16) {
Shinya Kitaoka 120a6e
        TPixel32 *pix = (TPixel32 *)buffer;
Shinya Kitaoka 120a6e
        int i         = -2;
shun-iwasawa cf34ed
        i += x0 * 2 * 4;
shun-iwasawa cf34ed
        for (int j = x0; j <= x1; j++) {
Toshihiro Shimizu 890ddd
#if defined(TNZ_MACHINE_CHANNEL_ORDER_MRGB)
Shinya Kitaoka 120a6e
          pix[j].m = m_rowBuffer[i = i + 2];
Shinya Kitaoka 120a6e
          pix[j].r = m_rowBuffer[i = i + 2];
Shinya Kitaoka 120a6e
          pix[j].g = m_rowBuffer[i = i + 2];
Shinya Kitaoka 120a6e
          pix[j].b = m_rowBuffer[i = i + 2];
Toshihiro Shimizu 890ddd
#elif defined(TNZ_MACHINE_CHANNEL_ORDER_RGBM)
Shinya Kitaoka 120a6e
          pix[j].r = m_rowBuffer[i = i + 2];
Shinya Kitaoka 120a6e
          pix[j].g = m_rowBuffer[i = i + 2];
Shinya Kitaoka 120a6e
          pix[j].b = m_rowBuffer[i = i + 2];
Shinya Kitaoka 120a6e
          pix[j].m = m_rowBuffer[i = i + 2];
Toshihiro Shimizu 890ddd
#elif defined(TNZ_MACHINE_CHANNEL_ORDER_BGRM)
Shinya Kitaoka 120a6e
          pix[j].b = m_rowBuffer[i = i + 2];
Shinya Kitaoka 120a6e
          pix[j].g = m_rowBuffer[i = i + 2];
Shinya Kitaoka 120a6e
          pix[j].r = m_rowBuffer[i = i + 2];
Shinya Kitaoka 120a6e
          pix[j].m = m_rowBuffer[i = i + 2];
Toshihiro Shimizu 890ddd
#elif defined(TNZ_MACHINE_CHANNEL_ORDER_MBGR)
Shinya Kitaoka 120a6e
          pix[j].m = m_rowBuffer[i = i + 2];
Shinya Kitaoka 120a6e
          pix[j].b = m_rowBuffer[i = i + 2];
Shinya Kitaoka 120a6e
          pix[j].g = m_rowBuffer[i = i + 2];
Shinya Kitaoka 120a6e
          pix[j].r = m_rowBuffer[i = i + 2];
Toshihiro Shimizu 890ddd
#else
Shinya Kitaoka 120a6e
#error "unknown channel order"
Toshihiro Shimizu 890ddd
#endif
shun-iwasawa 8b6d1f
shun-iwasawa 8b6d1f
          // premultiply here
shun-iwasawa 8b6d1f
          premult(pix[j]);
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      } else {
Shinya Kitaoka 120a6e
        TPixel32 *pix = (TPixel32 *)buffer;
Shinya Kitaoka 120a6e
        int i         = 0;
shun-iwasawa cf34ed
        i += x0 * 4;
shun-iwasawa cf34ed
        for (int j = x0; j <= x1; j++) {
Toshihiro Shimizu 890ddd
#if defined(TNZ_MACHINE_CHANNEL_ORDER_MRGB)
Shinya Kitaoka 120a6e
          pix[j].m = m_rowBuffer[i++];
Shinya Kitaoka 120a6e
          pix[j].r = m_rowBuffer[i++];
Shinya Kitaoka 120a6e
          pix[j].g = m_rowBuffer[i++];
Shinya Kitaoka 120a6e
          pix[j].b = m_rowBuffer[i++];
Toshihiro Shimizu 890ddd
#elif defined(TNZ_MACHINE_CHANNEL_ORDER_RGBM)
shun-iwasawa 8b6d1f
          pix[j].r = m_rowBuffer[i++];
shun-iwasawa 8b6d1f
          pix[j].g = m_rowBuffer[i++];
shun-iwasawa 8b6d1f
          pix[j].b = m_rowBuffer[i++];
shun-iwasawa 8b6d1f
          pix[j].m = m_rowBuffer[i++];
Toshihiro Shimizu 890ddd
#elif defined(TNZ_MACHINE_CHANNEL_ORDER_BGRM)
shun-iwasawa 8b6d1f
          pix[j].b = m_rowBuffer[i++];
shun-iwasawa 8b6d1f
          pix[j].g = m_rowBuffer[i++];
shun-iwasawa 8b6d1f
          pix[j].r = m_rowBuffer[i++];
shun-iwasawa 8b6d1f
          pix[j].m = m_rowBuffer[i++];
Toshihiro Shimizu 890ddd
#elif defined(TNZ_MACHINE_CHANNEL_ORDER_MBGR)
shun-iwasawa 8b6d1f
          pix[j].m = m_rowBuffer[i++];
shun-iwasawa 8b6d1f
          pix[j].b = m_rowBuffer[i++];
shun-iwasawa 8b6d1f
          pix[j].g = m_rowBuffer[i++];
shun-iwasawa 8b6d1f
          pix[j].r = m_rowBuffer[i++];
Toshihiro Shimizu 890ddd
#else
Shinya Kitaoka 120a6e
#error "unknown channel order"
Toshihiro Shimizu 890ddd
#endif
shun-iwasawa 8b6d1f
          // premultiply here
shun-iwasawa 8b6d1f
          premult(pix[j]);
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else  // qui gestisce RGB senza alpha.
Shinya Kitaoka 120a6e
    {       // grayscale e' gestito come RGB perche' si usa png_set_gray_to_rgb
Shinya Kitaoka 120a6e
      if (m_bit_depth == 16) {
Shinya Kitaoka 120a6e
        TPixel32 *pix = (TPixel32 *)buffer;
Shinya Kitaoka 120a6e
        int i         = -2;
shun-iwasawa cf34ed
        i += x0 * 2 * 3;
shun-iwasawa cf34ed
        for (int j = x0; j <= x1; j++) {
Shinya Kitaoka 120a6e
#if defined(TNZ_MACHINE_CHANNEL_ORDER_MRGB) ||                                 \
Shinya Kitaoka 120a6e
    defined(TNZ_MACHINE_CHANNEL_ORDER_RGBM)
Shinya Kitaoka 120a6e
          pix[j].r = m_rowBuffer[i = i + 2];
Shinya Kitaoka 120a6e
          pix[j].g = m_rowBuffer[i = i + 2];
Shinya Kitaoka 120a6e
          pix[j].b = m_rowBuffer[i = i + 2];
Shinya Kitaoka 120a6e
#elif defined(TNZ_MACHINE_CHANNEL_ORDER_MBGR) ||                               \
Shinya Kitaoka 120a6e
    defined(TNZ_MACHINE_CHANNEL_ORDER_BGRM)
Shinya Kitaoka 120a6e
          pix[j].b = m_rowBuffer[i = i + 2];
Shinya Kitaoka 120a6e
          pix[j].g = m_rowBuffer[i = i + 2];
Shinya Kitaoka 120a6e
          pix[j].r = m_rowBuffer[i = i + 2];
Toshihiro Shimizu 890ddd
#else
Shinya Kitaoka 120a6e
#error "unknown channel order"
Toshihiro Shimizu 890ddd
#endif
Shinya Kitaoka 120a6e
          pix[j].m = 255;
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      } else {
Shinya Kitaoka 120a6e
        TPixel32 *pix = (TPixel32 *)buffer;
Shinya Kitaoka 120a6e
        int i         = 0;
shun-iwasawa cf34ed
        i += x0 * 3;
shun-iwasawa cf34ed
        for (int j = x0; j <= x1; j++) {
Shinya Kitaoka 120a6e
#if defined(TNZ_MACHINE_CHANNEL_ORDER_MRGB) ||                                 \
Shinya Kitaoka 120a6e
    defined(TNZ_MACHINE_CHANNEL_ORDER_RGBM)
Shinya Kitaoka 120a6e
          pix[j].r = m_rowBuffer[i++];
Shinya Kitaoka 120a6e
          pix[j].g = m_rowBuffer[i++];
Shinya Kitaoka 120a6e
          pix[j].b = m_rowBuffer[i++];
Shinya Kitaoka 120a6e
#elif defined(TNZ_MACHINE_CHANNEL_ORDER_MBGR) ||                               \
Shinya Kitaoka 120a6e
    defined(TNZ_MACHINE_CHANNEL_ORDER_BGRM)
shun-iwasawa 8b6d1f
          pix[j].b = m_rowBuffer[i++];
shun-iwasawa 8b6d1f
          pix[j].g = m_rowBuffer[i++];
shun-iwasawa 8b6d1f
          pix[j].r = m_rowBuffer[i++];
Toshihiro Shimizu 890ddd
#else
Shinya Kitaoka 120a6e
#error "unknown channel order"
Toshihiro Shimizu 890ddd
#endif
Shinya Kitaoka 120a6e
          pix[j].m = 255;
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
shun-iwasawa cf34ed
  void writeRow(short *buffer, int x0, int x1) {
Shinya Kitaoka 120a6e
    if (m_color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
Martin van Zijl 9d02b2
        m_color_type == PNG_COLOR_TYPE_GRAY_ALPHA ||
shun-iwasawa 8b6d1f
        m_color_type == PNG_COLOR_TYPE_PALETTE) {  // PNG_COLOR_TYPE_PALETTE is
shun-iwasawa 8b6d1f
                                                   // expanded to RGBA
Shinya Kitaoka 120a6e
      TPixel64 *pix = (TPixel64 *)buffer;
Shinya Kitaoka 120a6e
      int i         = -2;  // 0;
shun-iwasawa cf34ed
      i += x0 * 2 * 4;
shun-iwasawa cf34ed
      for (int j = x0; j <= x1; j++) {
Shinya Kitaoka 120a6e
#if defined(TNZ_MACHINE_CHANNEL_ORDER_MRGB) ||                                 \
Shinya Kitaoka 120a6e
    defined(TNZ_MACHINE_CHANNEL_ORDER_RGBM)
Shinya Kitaoka 120a6e
        pix[j].r = mySwap(m_rowBuffer[i = i + 2]);  // i++
Shinya Kitaoka 120a6e
        pix[j].g = mySwap(m_rowBuffer[i = i + 2]);
Shinya Kitaoka 120a6e
        pix[j].b = mySwap(m_rowBuffer[i = i + 2]);
Shinya Kitaoka 120a6e
        pix[j].m = mySwap(m_rowBuffer[i = i + 2]);
Shinya Kitaoka 120a6e
#elif defined(TNZ_MACHINE_CHANNEL_ORDER_MBGR) ||                               \
Shinya Kitaoka 120a6e
    defined(TNZ_MACHINE_CHANNEL_ORDER_BGRM)
Shinya Kitaoka 120a6e
        pix[j].b = mySwap(m_rowBuffer[i = i + 2]);  // i++
Shinya Kitaoka 120a6e
        pix[j].g = mySwap(m_rowBuffer[i = i + 2]);
Shinya Kitaoka 120a6e
        pix[j].r = mySwap(m_rowBuffer[i = i + 2]);
Shinya Kitaoka 120a6e
        pix[j].m = mySwap(m_rowBuffer[i = i + 2]);
Toshihiro Shimizu 890ddd
#else
Shinya Kitaoka 120a6e
#error "unknown channel order"
Toshihiro Shimizu 890ddd
#endif
Shinya Kitaoka 120a6e
        // pix[j].m = 255;
shun-iwasawa 8b6d1f
shun-iwasawa 8b6d1f
        // premultiply here
shun-iwasawa 8b6d1f
        premult(pix[j]);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else  // qui gestisce RGB senza alpha.
Shinya Kitaoka 120a6e
    {       // grayscale e' gestito come RGB perche' si usa png_set_gray_to_rgb
Shinya Kitaoka 120a6e
      TPixel64 *pix = (TPixel64 *)buffer;
Shinya Kitaoka 120a6e
      int i         = -2;
shun-iwasawa cf34ed
      i += x0 * 2 * 3;
shun-iwasawa cf34ed
      for (int j = x0; j <= x1; j++) {
Shinya Kitaoka 120a6e
#if defined(TNZ_MACHINE_CHANNEL_ORDER_MRGB) ||                                 \
Shinya Kitaoka 120a6e
    defined(TNZ_MACHINE_CHANNEL_ORDER_RGBM)
Shinya Kitaoka 120a6e
        pix[j].r = mySwap(m_rowBuffer[i = i + 2]);
Shinya Kitaoka 120a6e
        pix[j].g = mySwap(m_rowBuffer[i = i + 2]);
Shinya Kitaoka 120a6e
        pix[j].b = mySwap(m_rowBuffer[i = i + 2]);
Shinya Kitaoka 120a6e
#elif defined(TNZ_MACHINE_CHANNEL_ORDER_MBGR) ||                               \
Shinya Kitaoka 120a6e
    defined(TNZ_MACHINE_CHANNEL_ORDER_BGRM)
Shinya Kitaoka 120a6e
        pix[j].b = mySwap(m_rowBuffer[i = i + 2]);
Shinya Kitaoka 120a6e
        pix[j].g = mySwap(m_rowBuffer[i = i + 2]);
Shinya Kitaoka 120a6e
        pix[j].r = mySwap(m_rowBuffer[i = i + 2]);
Toshihiro Shimizu 890ddd
#else
Shinya Kitaoka 120a6e
#error "unknown channel order"
Toshihiro Shimizu 890ddd
#endif
Shinya Kitaoka 120a6e
        pix[j].m = mySwap(255);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  void copyPixel(int count, int dstX, int dstDx, int dstY) {
Shinya Kitaoka 120a6e
    int channels = png_get_channels(m_png_ptr, m_info_ptr);
Shinya Kitaoka 120a6e
    int rowBytes = png_get_rowbytes(m_png_ptr, m_info_ptr);
Shinya Kitaoka 120a6e
    int lx       = m_info.m_lx;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if ((channels == 4 || channels == 3) && m_bit_depth == 16) {
Shinya Kitaoka 120a6e
      for (int i = 0; i < count; i += 2) {
Shinya Kitaoka 120a6e
        for (int j = 0; j < channels * 2; j++) {
Shinya Kitaoka 120a6e
          (m_tempBuffer.get() +
Shinya Kitaoka 120a6e
           (dstY * rowBytes))[(i * dstDx + dstX) * channels + j] =
Shinya Kitaoka 120a6e
              m_rowBuffer[i * channels + j];
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else if (channels == 2 && m_bit_depth == 16) {
Shinya Kitaoka 120a6e
      for (int i = 0; i < count; i += 2) {
Shinya Kitaoka 120a6e
        for (int j = 0; j < 4 * 2; j++) {
Shinya Kitaoka 120a6e
          (m_tempBuffer.get() +
Shinya Kitaoka 120a6e
           (dstY * rowBytes * 4))[(i * dstDx + dstX) * 4 + j] =
Shinya Kitaoka 120a6e
              m_rowBuffer[i * 4 + j];
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else if (channels == 1 && m_bit_depth == 16) {
Shinya Kitaoka 120a6e
      for (int i = 0; i < count; i += 2) {
Shinya Kitaoka 120a6e
        for (int j = 0; j < 3 * 2; j++) {
Shinya Kitaoka 120a6e
          (m_tempBuffer.get() +
Shinya Kitaoka 120a6e
           (dstY * rowBytes * 4))[(i * dstDx + dstX) * 3 + j] =
Shinya Kitaoka 120a6e
              m_rowBuffer[i * 3 + j];
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else if (channels == 1 && m_bit_depth == 8) {
Shinya Kitaoka 120a6e
      for (int i = 0; i < count; i++) {
Shinya Kitaoka 120a6e
        for (int j = 0; j < 3; j++) {
Shinya Kitaoka 120a6e
          (m_tempBuffer.get() +
Shinya Kitaoka 120a6e
           (dstY * rowBytes * 4))[(i * dstDx + dstX) * 3 + j] =
Shinya Kitaoka 120a6e
              m_rowBuffer[i * 3 + j];
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else if (channels == 2 && m_bit_depth == 8) {
Shinya Kitaoka 120a6e
      for (int i = 0; i < count; i++) {
Shinya Kitaoka 120a6e
        for (int j = 0; j < 4; j++) {
Shinya Kitaoka 120a6e
          (m_tempBuffer.get() +
Shinya Kitaoka 120a6e
           (dstY * rowBytes * 4))[(i * dstDx + dstX) * 4 + j] =
Shinya Kitaoka 120a6e
              m_rowBuffer[i * 4 + j];
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else if ((channels == 1 || channels == 2) && m_bit_depth < 8) {
Shinya Kitaoka 120a6e
      for (int i = 0; i < count; i++) {
Shinya Kitaoka 120a6e
        for (int j = 0; j < 3; j++) {
Shinya Kitaoka 120a6e
          (m_tempBuffer.get() + (dstY * lx * 3))[(i * dstDx + dstX) * 3 + j] =
Shinya Kitaoka 120a6e
              m_rowBuffer[i * 3 + j];
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      for (int i = 0; i < count; i++) {
Shinya Kitaoka 120a6e
        for (int j = 0; j < channels; j++) {
Shinya Kitaoka 120a6e
          (m_tempBuffer.get() +
Shinya Kitaoka 120a6e
           (dstY * rowBytes))[(i * dstDx + dstX) * channels + j] =
Shinya Kitaoka 120a6e
              m_rowBuffer[i * channels + j];
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  void readLineInterlace(char *buffer, int x0, int x1, int shrink) {
Shinya Kitaoka 120a6e
    // m_png_ptr->row_number è l'indice di riga che scorre quando chiamo la
Shinya Kitaoka 120a6e
    // png_read_row
Shinya Kitaoka 120a6e
    int rowNumber = png_get_current_row_number(m_png_ptr);
Shinya Kitaoka 120a6e
    // numRows è il numero di righe processate in ogni passo
Shinya Kitaoka 120a6e
    int numRows = (int)png_get_image_height(m_png_ptr, m_info_ptr) / 8;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    int passPng = png_get_current_pass_number(m_png_ptr);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    int passRow = 5 + (m_y & 1);  // passo desiderato per la riga corrente
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    int channels = png_get_channels(m_png_ptr, m_info_ptr);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    int rowBytes          = png_get_rowbytes(m_png_ptr, m_info_ptr);
Shinya Kitaoka 120a6e
    png_bytep row_pointer = m_rowBuffer.get();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    int lx = m_info.m_lx;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    while (passPng <= passRow &&
Shinya Kitaoka 120a6e
           rowNumber <=
Shinya Kitaoka 120a6e
               numRows)  // finchè il passo d'interlacciamento è minore o uguale
Shinya Kitaoka 120a6e
    // <             //del passo desiderato effettua tante volte le lettura
Shinya Kitaoka 120a6e
    // della riga
Shinya Kitaoka 120a6e
    // quant'è il passo desiderato per quella riga
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
      rowNumber = png_get_current_row_number(m_png_ptr);
Shinya Kitaoka 120a6e
      png_read_row(m_png_ptr, row_pointer, NULL);
Shinya Kitaoka 120a6e
      numRows = png_get_image_height(m_png_ptr, m_info_ptr);
Shinya Kitaoka 120a6e
      // devo memorizzare la riga letta nel buffer di appoggio in base al passo
Shinya Kitaoka 120a6e
      // di riga
Shinya Kitaoka 120a6e
      // e al blocchetto di appartenenza della riga
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      // copio i pixel che desidero nel buffer temporaneo
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      // il membro di PngReader copyPixel deve tener conto della riga processata
Shinya Kitaoka 120a6e
      // e del passo che si è effettuato ( e in base a quello so quanti pixel
Shinya Kitaoka 120a6e
      // copiare!)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (m_bit_depth == 16) {
Shinya Kitaoka 120a6e
        if (passPng == 0)
Shinya Kitaoka 120a6e
          copyPixel(lx / 4, 0, 8, rowNumber * 8);
Shinya Kitaoka 120a6e
        else if (passPng == 1)
Shinya Kitaoka 120a6e
          copyPixel(lx / 4, 8, 8, rowNumber * 8);
Shinya Kitaoka 120a6e
        else if (passPng == 2)
Shinya Kitaoka 120a6e
          copyPixel(lx / 2, 0, 4, rowNumber * 8 + 4);
Shinya Kitaoka 120a6e
        else if (passPng == 3)
Shinya Kitaoka 120a6e
          copyPixel(lx / 2, 4, 4, rowNumber * 4);
Shinya Kitaoka 120a6e
        else if (passPng == 4)
Shinya Kitaoka 120a6e
          copyPixel(lx, 0, 2, rowNumber * 4 + 2);
Shinya Kitaoka 120a6e
        else if (passPng == 5)
Shinya Kitaoka 120a6e
          copyPixel(lx, 2, 2, rowNumber * 2);
Shinya Kitaoka 120a6e
        else if (passPng == 6)
Shinya Kitaoka 120a6e
          copyPixel(2 * lx, 0, 1, rowNumber * 2 + 1);
Shinya Kitaoka 120a6e
      } else {
Shinya Kitaoka 120a6e
        if (passPng == 0)
Shinya Kitaoka 120a6e
          copyPixel((lx + 7) / 8, 0, 8, rowNumber * 8);
Shinya Kitaoka 120a6e
        else if (passPng == 1)
Shinya Kitaoka 120a6e
          copyPixel((lx + 3) / 8, 4, 8, rowNumber * 8);
Shinya Kitaoka 120a6e
        else if (passPng == 2)
Shinya Kitaoka 120a6e
          copyPixel((lx + 3) / 4, 0, 4, rowNumber * 8 + 4);
Shinya Kitaoka 120a6e
        else if (passPng == 3)
Shinya Kitaoka 120a6e
          copyPixel((lx + 1) / 4, 2, 4, rowNumber * 4);
Shinya Kitaoka 120a6e
        else if (passPng == 4)
Shinya Kitaoka 120a6e
          copyPixel((lx + 1) / 2, 0, 2, rowNumber * 4 + 2);
Shinya Kitaoka 120a6e
        else if (passPng == 5)
Shinya Kitaoka 120a6e
          copyPixel(lx / 2, 1, 2, rowNumber * 2);
Shinya Kitaoka 120a6e
        else if (passPng == 6)
Shinya Kitaoka 120a6e
          copyPixel(lx, 0, 1, rowNumber * 2 + 1);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      passPng = png_get_current_pass_number(m_png_ptr);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // fase di copia
Shinya Kitaoka 120a6e
    if (channels == 1 || channels == 2) {
Shinya Kitaoka 120a6e
      if (m_bit_depth < 8)
Shinya Kitaoka 120a6e
        memcpy(m_rowBuffer.get(), m_tempBuffer.get() + ((m_y)*lx * 3), lx * 3);
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        memcpy(m_rowBuffer.get(), m_tempBuffer.get() + ((m_y)*rowBytes * 4),
Shinya Kitaoka 120a6e
               rowBytes * 4);
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      memcpy(m_rowBuffer.get(), m_tempBuffer.get() + ((m_y)*rowBytes),
Shinya Kitaoka 120a6e
             rowBytes);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // fase di copia vecchia
Shinya Kitaoka 120a6e
    // memcpy(m_rowBuffer, m_tempBuffer+((m_y)*rowBytes), rowBytes);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // tutto quello che segue lo metto in una funzione in cui scrivo il buffer
Shinya Kitaoka 120a6e
    // di restituzione della readLine
shun-iwasawa cf34ed
    // è una funzione comune alle ReadLine
shun-iwasawa cf34ed
    writeRow(buffer, x0, x1);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  void readLineInterlace(short *buffer, int x0, int x1, int shrink) {
Shinya Kitaoka 120a6e
    // m_png_ptr->row_number è l'indice di riga che scorre quando chiamo la
Shinya Kitaoka 120a6e
    // png_read_row
Shinya Kitaoka 120a6e
    int rowNumber = png_get_current_row_number(m_png_ptr);
Shinya Kitaoka 120a6e
    // numRows è il numero di righe processate in ogni passo
Shinya Kitaoka 120a6e
    int numRows = png_get_image_height(m_png_ptr, m_info_ptr) / 8;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    int passPng = png_get_current_pass_number(
Shinya Kitaoka 120a6e
        m_png_ptr);  // conosco il passo d'interlacciamento
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    int passRow = 5 + (m_y & 1);  // passo desiderato per la riga corrente
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    int channels = png_get_channels(m_png_ptr, m_info_ptr);
Shinya Kitaoka 120a6e
    int lx       = m_info.m_lx;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    int rowBytes          = png_get_rowbytes(m_png_ptr, m_info_ptr);
Shinya Kitaoka 120a6e
    png_bytep row_pointer = m_rowBuffer.get();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    while (passPng <= passRow &&
Shinya Kitaoka 120a6e
           rowNumber <
Shinya Kitaoka 120a6e
               numRows)  // finchè il passo d'interlacciamento è minore o uguale
Shinya Kitaoka 120a6e
    // del passo desiderato effettua tante volte le lettura della riga
Shinya Kitaoka 120a6e
    // quant'è il passo desiderato per quella riga
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
      rowNumber = png_get_current_row_number(m_png_ptr);
Shinya Kitaoka 120a6e
      png_read_row(m_png_ptr, row_pointer, NULL);
Shinya Kitaoka 120a6e
      numRows = png_get_image_height(m_png_ptr, m_info_ptr);
Shinya Kitaoka 120a6e
      int lx  = m_info.m_lx;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      // devo memorizzare la riga letta nel buffer di appoggio in base al passo
Shinya Kitaoka 120a6e
      // di riga
Shinya Kitaoka 120a6e
      // e al blocchetto di appartenenza della riga
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      // copio i pixel che desidero nel buffer temporaneo
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      // il membro di PngReader copyPixel deve tener conto della riga processata
Shinya Kitaoka 120a6e
      // e del passo che si è effettuato ( e in base a quello so quanti pixel
Shinya Kitaoka 120a6e
      // copiare!)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      int channels = png_get_channels(m_png_ptr, m_info_ptr);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (passPng == 0)
Shinya Kitaoka 120a6e
        copyPixel(lx / 4, 0, 8, rowNumber * 8);
Shinya Kitaoka 120a6e
      else if (passPng == 1)
Shinya Kitaoka 120a6e
        copyPixel(lx / 4, 8, 8, rowNumber * 8);
Shinya Kitaoka 120a6e
      else if (passPng == 2)
Shinya Kitaoka 120a6e
        copyPixel(lx / 2, 0, 4, rowNumber * 8 + 4);
Shinya Kitaoka 120a6e
      else if (passPng == 3)
Shinya Kitaoka 120a6e
        copyPixel(lx / 2, 4, 4, rowNumber * 4);
Shinya Kitaoka 120a6e
      else if (passPng == 4)
Shinya Kitaoka 120a6e
        copyPixel(lx, 0, 2, rowNumber * 4 + 2);
Shinya Kitaoka 120a6e
      else if (passPng == 5)
Shinya Kitaoka 120a6e
        copyPixel(lx, 2, 2, rowNumber * 2);
Shinya Kitaoka 120a6e
      else if (passPng == 6)
Shinya Kitaoka 120a6e
        copyPixel(2 * lx, 0, 1, rowNumber * 2 + 1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      passPng = png_get_current_pass_number(m_png_ptr);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // fase di copia
Shinya Kitaoka 120a6e
    if (channels == 1 || channels == 2) {
Shinya Kitaoka 120a6e
      memcpy(m_rowBuffer.get(), m_tempBuffer.get() + ((m_y)*rowBytes * 4),
Shinya Kitaoka 120a6e
             rowBytes * 4);
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      memcpy(m_rowBuffer.get(), m_tempBuffer.get() + ((m_y)*rowBytes),
Shinya Kitaoka 120a6e
             rowBytes);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // fase di copia
Shinya Kitaoka 120a6e
    // memcpy(m_rowBuffer, m_tempBuffer+((m_y)*rowBytes), rowBytes);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // tutto quello che segue lo metto in una funzione in cui scrivo il buffer
Shinya Kitaoka 120a6e
    // di restituzione della readLine
shun-iwasawa cf34ed
    // è una funzione comune alle ReadLine
shun-iwasawa cf34ed
    writeRow(buffer, x0, x1);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=========================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Tiio::PngWriterProperties::PngWriterProperties()
Shinya Kitaoka 120a6e
    : m_matte("Alpha Channel", true)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
{
Shinya Kitaoka 120a6e
  bind(m_matte);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
shun-iwasawa e87e08
void Tiio::PngWriterProperties::updateTranslation() {
shun-iwasawa e87e08
  m_matte.setQStringName(tr("Alpha Channel"));
shun-iwasawa e87e08
}
shun-iwasawa e87e08
Toshihiro Shimizu 890ddd
//=========================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class PngWriter final : public Tiio::Writer {
Shinya Kitaoka 120a6e
  png_structp m_png_ptr;
Shinya Kitaoka 120a6e
  png_infop m_info_ptr;
Shinya Kitaoka 120a6e
  FILE *m_chan;
Shinya Kitaoka 120a6e
  bool m_matte;
Shinya Kitaoka 120a6e
  std::vector<tpixel> *m_colormap;</tpixel>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  PngWriter();
Shinya Kitaoka 120a6e
  ~PngWriter();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  void open(FILE *file, const TImageInfo &info) override;
Shinya Kitaoka 473e70
  void writeLine(char *buffer) override;
Shinya Kitaoka 473e70
  void writeLine(short *buffer) override;
Shinya Kitaoka 473e70
Shinya Kitaoka 473e70
  Tiio::RowOrder getRowOrder() const override { return Tiio::TOP2BOTTOM; }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  void flush() override;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  bool write64bitSupported() const override { return true; }
shun-iwasawa 93fdd4
  // m_matte is set to "Alpha Channel" property value in the function open()
shun-iwasawa 93fdd4
  bool writeAlphaSupported() const override { return m_matte; };
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
PngWriter::PngWriter()
Shinya Kitaoka 120a6e
    : m_png_ptr(0), m_info_ptr(0), m_matte(true), m_colormap(0) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
PngWriter::~PngWriter() {
Shinya Kitaoka 120a6e
  if (m_png_ptr) {
Shinya Kitaoka 120a6e
    png_destroy_write_struct(&m_png_ptr, &m_info_ptr);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (m_chan) {
Shinya Kitaoka 120a6e
    fflush(m_chan);
Shinya Kitaoka 120a6e
    m_chan = 0;
Shinya Kitaoka 120a6e
  }
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
Shinya Kitaoka 120a6e
void PngWriter::open(FILE *file, const TImageInfo &info) {
Shinya Kitaoka 120a6e
  m_info    = info;
Shinya Kitaoka 120a6e
  m_png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
Shinya Kitaoka 120a6e
                                      (png_voidp)0,  // user_error_ptr,
Shinya Kitaoka 120a6e
                                      0,             // user_error_fn,
Shinya Kitaoka 120a6e
                                      0);            // user_warning_fn);
Shinya Kitaoka 120a6e
  if (!m_png_ptr) return;
Shinya Kitaoka 120a6e
  m_info_ptr = png_create_info_struct(m_png_ptr);
Shinya Kitaoka 120a6e
  if (!m_info_ptr) {
Shinya Kitaoka 120a6e
    png_destroy_write_struct(&m_png_ptr, (png_infopp)0);
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_chan = file;
Shinya Kitaoka 120a6e
  png_init_io(m_png_ptr, m_chan);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (!m_properties) m_properties = new Tiio::PngWriterProperties();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TBoolProperty *alphaProp =
Shinya Kitaoka 120a6e
      (TBoolProperty *)(m_properties->getProperty("Alpha Channel"));
Shinya Kitaoka 120a6e
  TPointerProperty *colormap =
Shinya Kitaoka 120a6e
      (TPointerProperty *)(m_properties->getProperty("Colormap"));
Shinya Kitaoka 120a6e
  m_matte = (alphaProp && alphaProp->getValue()) ? true : false;
Shinya Kitaoka 120a6e
  if (colormap) m_colormap = (vector<tpixel> *)colormap->getValue();</tpixel>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TUINT32 x_pixels_per_meter = tround(m_info.m_dpix / 0.0254);
Shinya Kitaoka 120a6e
  TUINT32 y_pixels_per_meter = tround(m_info.m_dpiy / 0.0254);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (!m_colormap)
Shinya Kitaoka 120a6e
    png_set_IHDR(m_png_ptr, m_info_ptr, m_info.m_lx, m_info.m_ly,
Shinya Kitaoka 120a6e
                 info.m_bitsPerSample,
Shinya Kitaoka 120a6e
                 m_matte ? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_RGB,
Shinya Kitaoka 120a6e
                 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
Shinya Kitaoka 120a6e
                 PNG_FILTER_TYPE_DEFAULT);
Shinya Kitaoka 120a6e
  else {
Shinya Kitaoka 120a6e
    png_set_IHDR(m_png_ptr, m_info_ptr, m_info.m_lx, m_info.m_ly, 8,
Shinya Kitaoka 120a6e
                 PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE,
Shinya Kitaoka 120a6e
                 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
Shinya Kitaoka 120a6e
    for (unsigned int i = 0; i < m_colormap->size(); i++) {
Shinya Kitaoka 120a6e
      /*unsigned char red = (i>>5)&0x7;
Shinya Kitaoka 120a6e
      unsigned char green = (i>>2)&0x7;
Shinya Kitaoka 120a6e
      unsigned char blue = i&0x3;
Shinya Kitaoka 120a6e
      palette[i].red = (red>>1) | (red<<2) | (red<<5);
Shinya Kitaoka 120a6e
      palette[i].green = (green>>1) | (green<<2) | (green<<5);
Shinya Kitaoka 120a6e
      palette[i].blue = blue | (blue<<2) | (blue<<4) | (blue<<6);
Shinya Kitaoka 120a6e
      if (red==0 && green==0) alpha[i] = 0; else if (blue==0 && green==0)
Shinya Kitaoka 120a6e
      alpha[i] = 128; else alpha[i] = 255;*/
Shinya Kitaoka 120a6e
      palette[i].red   = (*m_colormap)[i].r;
Shinya Kitaoka 120a6e
      palette[i].green = (*m_colormap)[i].g;
Shinya Kitaoka 120a6e
      palette[i].blue  = (*m_colormap)[i].b;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    png_set_PLTE(m_png_ptr, m_info_ptr, palette, m_colormap->size());
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
shun-iwasawa 8b6d1f
  // png_set_dither(m_png_ptr, palette, 256, 256, 0, 1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#if defined(TNZ_MACHINE_CHANNEL_ORDER_MBGR)
Shinya Kitaoka 120a6e
  png_set_bgr(m_png_ptr);
Shinya Kitaoka 120a6e
  png_set_swap_alpha(m_png_ptr);
Toshihiro Shimizu 890ddd
#elif defined(TNZ_MACHINE_CHANNEL_ORDER_BGRM)
Shinya Kitaoka 120a6e
  png_set_bgr(m_png_ptr);
Toshihiro Shimizu 890ddd
#elif defined(TNZ_MACHINE_CHANNEL_ORDER_MRGB)
Shinya Kitaoka 120a6e
  png_set_swap_alpha(m_png_ptr);
Toshihiro Shimizu 890ddd
#elif !defined(TNZ_MACHINE_CHANNEL_ORDER_RGBM)
Shinya Kitaoka 120a6e
#error "unknownchannel order"
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  png_set_pHYs(m_png_ptr, m_info_ptr, x_pixels_per_meter, y_pixels_per_meter,
Shinya Kitaoka 120a6e
               1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (m_colormap && m_matte) {
Shinya Kitaoka 120a6e
    alpha[0] = 0;
Shinya Kitaoka 120a6e
    // png_set_tRNS(m_png_ptr, m_info_ptr, alpha, 1, PNG_COLOR_TYPE_PALETTE);
Shinya Kitaoka 120a6e
    png_color_16 bgcolor;
Shinya Kitaoka 120a6e
    bgcolor.index = 0;
Shinya Kitaoka 120a6e
    png_set_tRNS(m_png_ptr, m_info_ptr, alpha, 1, &bgcolor);
Shinya Kitaoka 120a6e
  }
shun-iwasawa 8b6d1f
shun-iwasawa 8b6d1f
  png_write_info(m_png_ptr, m_info_ptr);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PngWriter::flush() {
Shinya Kitaoka 120a6e
  png_write_end(m_png_ptr, m_info_ptr);
Shinya Kitaoka 120a6e
  fflush(m_chan);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PngWriter::writeLine(short *buffer) {
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    TPixel64 *pix = (TPixel64 *)buffer;
Shinya Kitaoka 120a6e
    unsigned short *tmp;
Shinya Kitaoka 120a6e
    tmp = (unsigned short *)malloc((m_info.m_lx + 1) * 3);
Shinya Kitaoka 120a6e
    // unsigned short tmp[10000];
Shinya Kitaoka 120a6e
    int k = 0;
shun-iwasawa e6b124
    for (int j = 0; j < m_info.m_lx; j++, pix++) {
shun-iwasawa e6b124
      // depremultiply here
shun-iwasawa e6b124
      TPixel64 depremult_pix(*pix);
shun-iwasawa e6b124
      if (m_matte && depremult_pix.m != 0) depremult(depremult_pix);
shun-iwasawa e6b124
Shinya Kitaoka 120a6e
#if defined(TNZ_MACHINE_CHANNEL_ORDER_MRGB) ||                                 \
Shinya Kitaoka 120a6e
    defined(TNZ_MACHINE_CHANNEL_ORDER_RGBM)
Shinya Kitaoka 120a6e
      tmp[k++] = mySwap(pix->r);
Shinya Kitaoka 120a6e
      tmp[k++] = mySwap(pix->g);
Shinya Kitaoka 120a6e
      tmp[k++] = mySwap(pix->b);
Shinya Kitaoka 120a6e
#elif defined(TNZ_MACHINE_CHANNEL_ORDER_MBGR) ||                               \
Shinya Kitaoka 120a6e
    defined(TNZ_MACHINE_CHANNEL_ORDER_BGRM)
Shinya Kitaoka 120a6e
      tmp[k++] = mySwap(pix->b);
Shinya Kitaoka 120a6e
      tmp[k++] = mySwap(pix->g);
Shinya Kitaoka 120a6e
      tmp[k++] = mySwap(pix->r);
Toshihiro Shimizu 890ddd
#else
Shinya Kitaoka 120a6e
#error "unknown channel order"
Toshihiro Shimizu 890ddd
#endif
shun-iwasawa e6b124
      if (m_matte)
shun-iwasawa e6b124
        tmp[k++] = mySwap(pix->m);  // ?? does it take care MRGB or MBGR case?
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    png_write_row(m_png_ptr, (unsigned char *)tmp);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=========================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PngWriter::writeLine(char *buffer) {
Shinya Kitaoka 120a6e
  // TBoolProperty* alphaProp =
Shinya Kitaoka 120a6e
  // (TBoolProperty*)(m_properties->getProperty("Alpha Channel"));
Shinya Kitaoka 120a6e
  if (m_matte || m_colormap) {
shun-iwasawa e6b124
    unsigned char *tmp = new unsigned char[(m_info.m_lx + 1) * 4];
shun-iwasawa e6b124
    TPixel32 *pix      = (TPixel32 *)buffer;
shun-iwasawa e6b124
    int k              = 0;
shun-iwasawa e6b124
    for (int j = 0; j < m_info.m_lx; j++, pix++) {
shun-iwasawa e6b124
      // depremultiply here
shun-iwasawa e6b124
      TPixel32 depremult_pix(*pix);
shun-iwasawa e6b124
      if (depremult_pix.m != 0) depremult(depremult_pix);
shun-iwasawa e6b124
#if defined(TNZ_MACHINE_CHANNEL_ORDER_MRGB)
shun-iwasawa e6b124
      tmp[k++] = depremult_pix.m;
shun-iwasawa e6b124
      tmp[k++] = depremult_pix.r;
shun-iwasawa e6b124
      tmp[k++] = depremult_pix.g;
shun-iwasawa e6b124
      tmp[k++] = depremult_pix.b;
shun-iwasawa e6b124
#elif defined(TNZ_MACHINE_CHANNEL_ORDER_RGBM)
shun-iwasawa e6b124
      tmp[k++] = depremult_pix.r;
shun-iwasawa e6b124
      tmp[k++] = depremult_pix.g;
shun-iwasawa e6b124
      tmp[k++] = depremult_pix.b;
shun-iwasawa e6b124
      tmp[k++] = depremult_pix.m;
shun-iwasawa e6b124
#elif defined(TNZ_MACHINE_CHANNEL_ORDER_MBGR)
shun-iwasawa e6b124
      tmp[k++] = depremult_pix.m;
shun-iwasawa e6b124
      tmp[k++] = depremult_pix.b;
shun-iwasawa e6b124
      tmp[k++] = depremult_pix.g;
shun-iwasawa e6b124
      tmp[k++] = depremult_pix.r;
shun-iwasawa e6b124
#elif defined(TNZ_MACHINE_CHANNEL_ORDER_BGRM)
shun-iwasawa 8b6d1f
      tmp[k++] = depremult_pix.b;
shun-iwasawa 8b6d1f
      tmp[k++] = depremult_pix.g;
shun-iwasawa 8b6d1f
      tmp[k++] = depremult_pix.r;
shun-iwasawa 8b6d1f
      tmp[k++] = depremult_pix.m;
shun-iwasawa e6b124
#else
shun-iwasawa e6b124
#error "unknown channel order"
shun-iwasawa e6b124
#endif
shun-iwasawa e6b124
    }
shun-iwasawa e6b124
    png_write_row(m_png_ptr, tmp);
shun-iwasawa e6b124
    delete[] tmp;
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    TPixel32 *pix      = (TPixel32 *)buffer;
shun-iwasawa e6b124
    unsigned char *tmp = new unsigned char[(m_info.m_lx + 1) * 3];
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    int k = 0;
Shinya Kitaoka 120a6e
    for (int j = 0; j < m_info.m_lx; j++) {
shun-iwasawa 8b6d1f
      // tmp = (pix->r&0xe0)|((pix->g&0xe0)>>3) | ((pix->b&0xc0)>>6);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
#if defined(TNZ_MACHINE_CHANNEL_ORDER_MRGB) ||                                 \
Shinya Kitaoka 120a6e
    defined(TNZ_MACHINE_CHANNEL_ORDER_RGBM)
Shinya Kitaoka 120a6e
      tmp[k++] = pix->r;
Shinya Kitaoka 120a6e
      tmp[k++] = pix->g;
Shinya Kitaoka 120a6e
      tmp[k++] = pix->b;
Shinya Kitaoka 120a6e
#elif defined(TNZ_MACHINE_CHANNEL_ORDER_MBGR) ||                               \
Shinya Kitaoka 120a6e
    defined(TNZ_MACHINE_CHANNEL_ORDER_BGRM)
Shinya Kitaoka 120a6e
      tmp[k++] = pix->b;
Shinya Kitaoka 120a6e
      tmp[k++] = pix->g;
Shinya Kitaoka 120a6e
      tmp[k++] = pix->r;
Toshihiro Shimizu 890ddd
#else
Shinya Kitaoka 120a6e
#error "unknown channel order"
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      ++pix;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    png_write_row(m_png_ptr, tmp);
shun-iwasawa e6b124
    delete[] tmp;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=========================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
Tiio::Reader *Tiio::makePngReader() { return new PngReader(); }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
Tiio::Writer *Tiio::makePngWriter() { return new PngWriter(); }