|
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 |
|
|
Shinya Kitaoka |
120a6e |
writeRow(buffer);
|
|
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 |
|
|
Shinya Kitaoka |
120a6e |
writeRow(buffer);
|
|
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 |
|
|
Shinya Kitaoka |
120a6e |
void writeRow(char *buffer) {
|
|
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;
|
|
Shinya Kitaoka |
120a6e |
for (int j = 0; j < m_info.m_lx; 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;
|
|
Shinya Kitaoka |
120a6e |
for (int j = 0; j < m_info.m_lx; 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;
|
|
Shinya Kitaoka |
120a6e |
for (int j = 0; j < m_info.m_lx; 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;
|
|
Shinya Kitaoka |
120a6e |
for (int j = 0; j < m_info.m_lx; 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 |
|
|
Shinya Kitaoka |
120a6e |
void writeRow(short *buffer) {
|
|
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;
|
|
Shinya Kitaoka |
120a6e |
for (int j = 0; j < m_info.m_lx; 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;
|
|
Shinya Kitaoka |
120a6e |
for (int j = 0; j < m_info.m_lx; 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
|
|
Shinya Kitaoka |
120a6e |
//è una funzione comune alle ReadLine
|
|
Shinya Kitaoka |
120a6e |
writeRow(buffer);
|
|
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
|
|
Shinya Kitaoka |
120a6e |
//è una funzione comune alle ReadLine
|
|
Shinya Kitaoka |
120a6e |
writeRow(buffer);
|
|
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(); }
|