|
|
|
@ -181,8 +181,6 @@ PngDecoder::PngDecoder() |
|
|
|
|
{ |
|
|
|
|
m_signature = "\x89\x50\x4e\x47\xd\xa\x1a\xa"; |
|
|
|
|
m_color_type = 0; |
|
|
|
|
m_png_ptr = nullptr; |
|
|
|
|
m_info_ptr = m_end_info = nullptr; |
|
|
|
|
m_f = 0; |
|
|
|
|
m_buf_supported = true; |
|
|
|
|
m_buf_pos = 0; |
|
|
|
@ -205,15 +203,6 @@ PngDecoder::~PngDecoder() |
|
|
|
|
fclose( m_f ); |
|
|
|
|
m_f = nullptr; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if( m_png_ptr ) |
|
|
|
|
{ |
|
|
|
|
png_structp png_ptr = (png_structp)m_png_ptr; |
|
|
|
|
png_infop info_ptr = (png_infop)m_info_ptr; |
|
|
|
|
png_infop end_info = (png_infop)m_end_info; |
|
|
|
|
png_destroy_read_struct( &png_ptr, &info_ptr, &end_info ); |
|
|
|
|
m_png_ptr = m_info_ptr = m_end_info = nullptr; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ImageDecoder PngDecoder::newDecoder() const |
|
|
|
@ -240,164 +229,149 @@ bool PngDecoder::readHeader() |
|
|
|
|
{ |
|
|
|
|
volatile bool result = false; |
|
|
|
|
|
|
|
|
|
png_structp png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, 0, 0, 0 ); |
|
|
|
|
png_infop info_ptr = nullptr; |
|
|
|
|
png_infop end_info = nullptr; |
|
|
|
|
PngPtrs png_ptrs; |
|
|
|
|
png_structp png_ptr = png_ptrs.getPng(); |
|
|
|
|
png_infop info_ptr = png_ptrs.getInfo(); |
|
|
|
|
png_infop end_info = png_ptrs.getEndInfo(); |
|
|
|
|
|
|
|
|
|
if( png_ptr ) |
|
|
|
|
if( png_ptr && info_ptr && end_info ) |
|
|
|
|
{ |
|
|
|
|
info_ptr = png_create_info_struct( png_ptr ); |
|
|
|
|
end_info = png_create_info_struct( png_ptr ); |
|
|
|
|
|
|
|
|
|
m_buf_pos = 0; |
|
|
|
|
|
|
|
|
|
if( info_ptr && end_info ) |
|
|
|
|
if( setjmp( png_jmpbuf( png_ptr ) ) == 0 ) |
|
|
|
|
{ |
|
|
|
|
if( setjmp( png_jmpbuf( png_ptr ) ) == 0 ) |
|
|
|
|
{ |
|
|
|
|
unsigned char sig[8]; |
|
|
|
|
uint32_t id = 0; |
|
|
|
|
Chunk chunk; |
|
|
|
|
unsigned char sig[8]; |
|
|
|
|
uint32_t id = 0; |
|
|
|
|
Chunk chunk; |
|
|
|
|
|
|
|
|
|
if( !m_buf.empty() ) |
|
|
|
|
png_set_read_fn(png_ptr, this, (png_rw_ptr)readDataFromBuf ); |
|
|
|
|
else |
|
|
|
|
if( !m_buf.empty() ) |
|
|
|
|
png_set_read_fn(png_ptr, this, (png_rw_ptr)readDataFromBuf ); |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
m_f = fopen(m_filename.c_str(), "rb"); |
|
|
|
|
if (!m_f) |
|
|
|
|
{ |
|
|
|
|
m_f = fopen(m_filename.c_str(), "rb"); |
|
|
|
|
if (!m_f) |
|
|
|
|
{ |
|
|
|
|
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
png_init_io(png_ptr, m_f); |
|
|
|
|
|
|
|
|
|
if (fread(sig, 1, 8, m_f)) |
|
|
|
|
id = read_chunk(m_chunkIHDR); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
png_init_io(png_ptr, m_f); |
|
|
|
|
|
|
|
|
|
if (id != id_IHDR) |
|
|
|
|
{ |
|
|
|
|
read_from_io(&sig, 8, 1); |
|
|
|
|
if (fread(sig, 1, 8, m_f)) |
|
|
|
|
id = read_chunk(m_chunkIHDR); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (id != id_IHDR) |
|
|
|
|
{ |
|
|
|
|
read_from_io(&sig, 8, 1); |
|
|
|
|
id = read_chunk(m_chunkIHDR); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!(id == id_IHDR && m_chunkIHDR.p.size() == 25)) |
|
|
|
|
{ |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!(id == id_IHDR && m_chunkIHDR.p.size() == 25)) |
|
|
|
|
while (true) |
|
|
|
|
{ |
|
|
|
|
m_is_fcTL_loaded = false; |
|
|
|
|
id = read_chunk(chunk); |
|
|
|
|
|
|
|
|
|
if ((m_f && feof(m_f)) || (!m_buf.empty() && m_buf_pos > m_buf.total())) |
|
|
|
|
{ |
|
|
|
|
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
while (true) |
|
|
|
|
if (id == id_IDAT) |
|
|
|
|
{ |
|
|
|
|
m_is_fcTL_loaded = false; |
|
|
|
|
id = read_chunk(chunk); |
|
|
|
|
|
|
|
|
|
if ((m_f && feof(m_f)) || (!m_buf.empty() && m_buf_pos > m_buf.total())) |
|
|
|
|
{ |
|
|
|
|
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (id == id_IDAT) |
|
|
|
|
{ |
|
|
|
|
if (m_f) |
|
|
|
|
fseek(m_f, 0, SEEK_SET); |
|
|
|
|
else |
|
|
|
|
m_buf_pos = 0; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
if (m_f) |
|
|
|
|
fseek(m_f, 0, SEEK_SET); |
|
|
|
|
else |
|
|
|
|
m_buf_pos = 0; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (id == id_acTL && chunk.p.size() == 20) |
|
|
|
|
{ |
|
|
|
|
m_animation.loop_count = png_get_uint_32(&chunk.p[12]); |
|
|
|
|
|
|
|
|
|
if (chunk.p[8] > 0) |
|
|
|
|
{ |
|
|
|
|
chunk.p[8] = 0; |
|
|
|
|
chunk.p[9] = 0; |
|
|
|
|
m_frame_count = png_get_uint_32(&chunk.p[8]); |
|
|
|
|
m_frame_count++; |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
m_frame_count = png_get_uint_32(&chunk.p[8]); |
|
|
|
|
} |
|
|
|
|
if (id == id_acTL && chunk.p.size() == 20) |
|
|
|
|
{ |
|
|
|
|
m_animation.loop_count = png_get_uint_32(&chunk.p[12]); |
|
|
|
|
|
|
|
|
|
if (id == id_fcTL) |
|
|
|
|
if (chunk.p[8] > 0) |
|
|
|
|
{ |
|
|
|
|
m_is_fcTL_loaded = true; |
|
|
|
|
w0 = png_get_uint_32(&chunk.p[12]); |
|
|
|
|
h0 = png_get_uint_32(&chunk.p[16]); |
|
|
|
|
x0 = png_get_uint_32(&chunk.p[20]); |
|
|
|
|
y0 = png_get_uint_32(&chunk.p[24]); |
|
|
|
|
delay_num = png_get_uint_16(&chunk.p[28]); |
|
|
|
|
delay_den = png_get_uint_16(&chunk.p[30]); |
|
|
|
|
dop = chunk.p[32]; |
|
|
|
|
bop = chunk.p[33]; |
|
|
|
|
chunk.p[8] = 0; |
|
|
|
|
chunk.p[9] = 0; |
|
|
|
|
m_frame_count = png_get_uint_32(&chunk.p[8]); |
|
|
|
|
m_frame_count++; |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
m_frame_count = png_get_uint_32(&chunk.p[8]); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (id == id_bKGD) |
|
|
|
|
{ |
|
|
|
|
int bgcolor = png_get_uint_32(&chunk.p[8]); |
|
|
|
|
m_animation.bgcolor[3] = (bgcolor >> 24) & 0xFF; |
|
|
|
|
m_animation.bgcolor[2] = (bgcolor >> 16) & 0xFF; |
|
|
|
|
m_animation.bgcolor[1] = (bgcolor >> 8) & 0xFF; |
|
|
|
|
m_animation.bgcolor[0] = bgcolor & 0xFF; |
|
|
|
|
} |
|
|
|
|
if (id == id_fcTL) |
|
|
|
|
{ |
|
|
|
|
m_is_fcTL_loaded = true; |
|
|
|
|
w0 = png_get_uint_32(&chunk.p[12]); |
|
|
|
|
h0 = png_get_uint_32(&chunk.p[16]); |
|
|
|
|
x0 = png_get_uint_32(&chunk.p[20]); |
|
|
|
|
y0 = png_get_uint_32(&chunk.p[24]); |
|
|
|
|
delay_num = png_get_uint_16(&chunk.p[28]); |
|
|
|
|
delay_den = png_get_uint_16(&chunk.p[30]); |
|
|
|
|
dop = chunk.p[32]; |
|
|
|
|
bop = chunk.p[33]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (id == id_PLTE || id == id_tRNS) |
|
|
|
|
m_chunksInfo.push_back(chunk); |
|
|
|
|
if (id == id_bKGD) |
|
|
|
|
{ |
|
|
|
|
int bgcolor = png_get_uint_32(&chunk.p[8]); |
|
|
|
|
m_animation.bgcolor[3] = (bgcolor >> 24) & 0xFF; |
|
|
|
|
m_animation.bgcolor[2] = (bgcolor >> 16) & 0xFF; |
|
|
|
|
m_animation.bgcolor[1] = (bgcolor >> 8) & 0xFF; |
|
|
|
|
m_animation.bgcolor[0] = bgcolor & 0xFF; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
png_uint_32 wdth, hght; |
|
|
|
|
int bit_depth, color_type, num_trans=0; |
|
|
|
|
png_bytep trans; |
|
|
|
|
png_color_16p trans_values; |
|
|
|
|
if (id == id_PLTE || id == id_tRNS) |
|
|
|
|
m_chunksInfo.push_back(chunk); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
png_uint_32 wdth, hght; |
|
|
|
|
int bit_depth, color_type, num_trans=0; |
|
|
|
|
png_bytep trans; |
|
|
|
|
png_color_16p trans_values; |
|
|
|
|
|
|
|
|
|
png_read_info( png_ptr, info_ptr ); |
|
|
|
|
png_get_IHDR(png_ptr, info_ptr, &wdth, &hght, |
|
|
|
|
&bit_depth, &color_type, 0, 0, 0); |
|
|
|
|
png_read_info( png_ptr, info_ptr ); |
|
|
|
|
png_get_IHDR(png_ptr, info_ptr, &wdth, &hght, |
|
|
|
|
&bit_depth, &color_type, 0, 0, 0); |
|
|
|
|
|
|
|
|
|
m_width = (int)wdth; |
|
|
|
|
m_height = (int)hght; |
|
|
|
|
m_color_type = color_type; |
|
|
|
|
m_bit_depth = bit_depth; |
|
|
|
|
m_width = (int)wdth; |
|
|
|
|
m_height = (int)hght; |
|
|
|
|
m_color_type = color_type; |
|
|
|
|
m_bit_depth = bit_depth; |
|
|
|
|
|
|
|
|
|
if (bit_depth <= 8 || bit_depth == 16) |
|
|
|
|
if (bit_depth <= 8 || bit_depth == 16) |
|
|
|
|
{ |
|
|
|
|
switch (color_type) |
|
|
|
|
{ |
|
|
|
|
switch (color_type) |
|
|
|
|
{ |
|
|
|
|
case PNG_COLOR_TYPE_RGB: |
|
|
|
|
case PNG_COLOR_TYPE_PALETTE: |
|
|
|
|
png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, &trans_values); |
|
|
|
|
if (num_trans > 0) |
|
|
|
|
m_type = CV_8UC4; |
|
|
|
|
else |
|
|
|
|
m_type = CV_8UC3; |
|
|
|
|
break; |
|
|
|
|
case PNG_COLOR_TYPE_GRAY_ALPHA: |
|
|
|
|
case PNG_COLOR_TYPE_RGB_ALPHA: |
|
|
|
|
case PNG_COLOR_TYPE_RGB: |
|
|
|
|
case PNG_COLOR_TYPE_PALETTE: |
|
|
|
|
png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, &trans_values); |
|
|
|
|
if (num_trans > 0) |
|
|
|
|
m_type = CV_8UC4; |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
m_type = CV_8UC1; |
|
|
|
|
} |
|
|
|
|
if (bit_depth == 16) |
|
|
|
|
m_type = CV_MAKETYPE(CV_16U, CV_MAT_CN(m_type)); |
|
|
|
|
result = true; |
|
|
|
|
else |
|
|
|
|
m_type = CV_8UC3; |
|
|
|
|
break; |
|
|
|
|
case PNG_COLOR_TYPE_GRAY_ALPHA: |
|
|
|
|
case PNG_COLOR_TYPE_RGB_ALPHA: |
|
|
|
|
m_type = CV_8UC4; |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
m_type = CV_8UC1; |
|
|
|
|
} |
|
|
|
|
if (bit_depth == 16) |
|
|
|
|
m_type = CV_MAKETYPE(CV_16U, CV_MAT_CN(m_type)); |
|
|
|
|
result = true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if(result) |
|
|
|
|
{ |
|
|
|
|
m_png_ptr = png_ptr; |
|
|
|
|
m_info_ptr = info_ptr; |
|
|
|
|
m_end_info = end_info; |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); |
|
|
|
|
m_png_ptrs = std::move(png_ptrs); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return result; |
|
|
|
@ -430,8 +404,8 @@ bool PngDecoder::readData( Mat& img ) |
|
|
|
|
frameCur.setMat(mat_cur); |
|
|
|
|
|
|
|
|
|
processing_start((void*)&frameRaw, mat_cur); |
|
|
|
|
png_structp png_ptr = (png_structp)m_png_ptr; |
|
|
|
|
png_infop info_ptr = (png_infop)m_info_ptr; |
|
|
|
|
png_structp png_ptr = m_png_ptrs.getPng(); |
|
|
|
|
png_infop info_ptr = m_png_ptrs.getInfo(); |
|
|
|
|
|
|
|
|
|
while (true) |
|
|
|
|
{ |
|
|
|
@ -540,11 +514,11 @@ bool PngDecoder::readData( Mat& img ) |
|
|
|
|
unsigned char** buffer = _buffer.data(); |
|
|
|
|
bool color = img.channels() > 1; |
|
|
|
|
|
|
|
|
|
png_structp png_ptr = (png_structp)m_png_ptr; |
|
|
|
|
png_infop info_ptr = (png_infop)m_info_ptr; |
|
|
|
|
png_infop end_info = (png_infop)m_end_info; |
|
|
|
|
png_structp png_ptr = m_png_ptrs.getPng(); |
|
|
|
|
png_infop info_ptr = m_png_ptrs.getInfo(); |
|
|
|
|
png_infop end_info = m_png_ptrs.getEndInfo(); |
|
|
|
|
|
|
|
|
|
if( m_png_ptr && m_info_ptr && m_end_info && m_width && m_height ) |
|
|
|
|
if( png_ptr && info_ptr && end_info && m_width && m_height ) |
|
|
|
|
{ |
|
|
|
|
if( setjmp( png_jmpbuf ( png_ptr ) ) == 0 ) |
|
|
|
|
{ |
|
|
|
@ -735,30 +709,20 @@ bool PngDecoder::processing_start(void* frame_ptr, const Mat& img) |
|
|
|
|
{ |
|
|
|
|
static uint8_t header[8] = { 137, 80, 78, 71, 13, 10, 26, 10 }; |
|
|
|
|
|
|
|
|
|
if (m_png_ptr) |
|
|
|
|
{ |
|
|
|
|
png_structp png_ptr = (png_structp)m_png_ptr; |
|
|
|
|
png_infop info_ptr = (png_infop)m_info_ptr; |
|
|
|
|
png_infop end_info = (png_infop)m_end_info; |
|
|
|
|
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); |
|
|
|
|
m_png_ptr = m_info_ptr = m_end_info = nullptr; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); |
|
|
|
|
png_infop info_ptr = png_create_info_struct(png_ptr); |
|
|
|
|
|
|
|
|
|
m_png_ptr = png_ptr; |
|
|
|
|
m_info_ptr = info_ptr; |
|
|
|
|
PngPtrs png_ptrs; |
|
|
|
|
png_structp png_ptr = png_ptrs.getPng(); |
|
|
|
|
png_infop info_ptr = png_ptrs.getInfo(); |
|
|
|
|
|
|
|
|
|
if (!png_ptr || !info_ptr) |
|
|
|
|
if (!png_ptr || !info_ptr) { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (setjmp(png_jmpbuf(png_ptr))) |
|
|
|
|
{ |
|
|
|
|
png_destroy_read_struct(&png_ptr, &info_ptr, 0); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
m_png_ptrs = std::move(png_ptrs); |
|
|
|
|
png_set_crc_action(png_ptr, PNG_CRC_QUIET_USE, PNG_CRC_QUIET_USE); |
|
|
|
|
png_set_progressive_read_fn(png_ptr, frame_ptr, (png_progressive_info_ptr)info_fn, row_fn, NULL); |
|
|
|
|
|
|
|
|
@ -787,24 +751,22 @@ bool PngDecoder::processing_finish() |
|
|
|
|
{ |
|
|
|
|
static uint8_t footer[12] = { 0, 0, 0, 0, 73, 69, 78, 68, 174, 66, 96, 130 }; |
|
|
|
|
|
|
|
|
|
png_structp png_ptr = (png_structp)m_png_ptr; |
|
|
|
|
png_infop info_ptr = (png_infop)m_info_ptr; |
|
|
|
|
png_infop end_info = (png_infop)m_end_info; |
|
|
|
|
png_structp png_ptr = m_png_ptrs.getPng(); |
|
|
|
|
png_infop info_ptr = m_png_ptrs.getInfo(); |
|
|
|
|
|
|
|
|
|
if (!png_ptr) |
|
|
|
|
if (!png_ptr) { |
|
|
|
|
m_png_ptrs.clear(); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (setjmp(png_jmpbuf(png_ptr))) |
|
|
|
|
{ |
|
|
|
|
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); |
|
|
|
|
m_png_ptrs.clear(); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
png_process_data(png_ptr, info_ptr, footer, 12); |
|
|
|
|
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); |
|
|
|
|
m_png_ptr = nullptr; |
|
|
|
|
m_info_ptr = nullptr; |
|
|
|
|
m_end_info = nullptr; |
|
|
|
|
m_png_ptrs.clear(); |
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|