/* * @brief get next apng frame */ void apng_ani::next_frame() { _reading = false; // setup new frame (if frame doesn't already exist) // always do if not caching // don't do if caching & already have frame if (_cache == false || (_frames.size() <= current_frame)) { if (current_frame > 0) { if (_dispose_op == 1) { // clear previous frame region of output buffer to fully transparent black for (uint row = 0; row < _frameh; ++row) { memset(&frame.data.at((_y_offset+row) * _row_len + _x_offset * 4), 0, _framew * 4); } } else if (_dispose_op == 2) { // revert previous frames region of output buffer to previous contents for (uint row = 0; row < _frameh; ++row) { uint pos = (_y_offset+row) * _row_len + _x_offset * 4; memcpy(&frame.data.at(pos), &_frame_next.data.at(pos), _framew * 4); } } // default is to do nothing with output buffer } while (cftell(_cfp) < _frame_offsets.at(current_frame+1)) { _process_chunk(); } nprintf(("apng", "apng next_frame; new (%03i/%03u/%03i) (%u) (%u) %03u|%03u %03u|%03u (%02u) (%04f)\n", current_frame, static_cast<uint>(_frames.size()), nframes, _dispose_op, _blend_op, _framew, _x_offset, _frameh, _y_offset, static_cast<uint>(_frame_offsets.size()), frame.delay)); if (_got_IDAT && _processing_finish()) { _apng_failed("couldn't finish fdat apng frame"); } if (_dispose_op == 2) { // revert to previous; so save the current frame region for later for (uint row = 0; row < _frameh; ++row) { uint pos = (_y_offset+row) * _row_len + _x_offset * 4; memcpy(&_frame_next.data.at(pos), &frame.data.at(pos), _framew * 4); } } _compose_frame(); if (_cache == true) _frames.push_back(frame); } else { if (current_frame < nframes) { nprintf(("apng", "apng next_frame; used old (%03i/%03u)\n", current_frame, static_cast<uint>(_frames.size()))); frame = _frames.at(current_frame); } } ++current_frame; }
void AudioEffectDelayInstance::process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count) { int todo = p_frame_count; while(todo) { int to_mix = MIN(todo,256); //can't mix too much _process_chunk(p_src_frames,p_dst_frames,to_mix); p_src_frames+=to_mix; p_dst_frames+=to_mix; todo-=to_mix; } }
/* * @brief Get info about the apng * @note Also validates the apng & sets it up to have frames read * * @retval PNG_ERROR_NONE (0), otherwise will raise exception */ int apng_ani::load_header() { char filename[MAX_FILENAME_LEN]; strcpy_s(filename, _filename.c_str()); char *p = strchr( filename, '.' ); if ( p != nullptr ) *p = 0; strcat_s( filename, ".png" ); _cfp = cfopen( filename , "rb" ); if ( _cfp == nullptr) { _apng_failed("couldn't open filename"); } _reading = true; ubyte sig[8]; if (cfread(sig, 8, 1, _cfp) != 1) { _apng_failed("cfread of png signature failed"); } if (png_sig_cmp(sig, 0, 8) != 0) { _apng_failed("file has invalid png signature"); } // setup chunk sizes before use _chunk_IHDR.data.resize(25); // fixed IHDR chunk size _chunk.data.resize(25); // match the other sizes, maybe waste up to 13 bytes (ooooh) _id = _read_chunk(_chunk_IHDR); if (_id != id_IHDR || _chunk_IHDR.size != 25) { _apng_failed("failed to read IHDR chunk"); } w = png_get_uint_32(&_chunk_IHDR.data[8]); h = png_get_uint_32(&_chunk_IHDR.data[12]); _row_len = w * 4; // setup frames & keep bm_create happy _image_size = _row_len * h; frame.data.reserve(_image_size); // alloc only once frame.data.assign(_image_size, 0); // all transparent black per spec frame.rows.resize(h); _frame_raw.data.resize(_image_size); _frame_raw.rows.resize(h); _frame_next.data.resize(_image_size); _frame_next.rows.resize(h); for (uint i = 0; i < h; ++i) { // everything is correctly sized above; avoid .at() error checks frame.rows[i] = &frame.data[i * _row_len]; _frame_raw.rows[i] = &_frame_raw.data[i * _row_len]; _frame_next.rows[i] = &_frame_next.data[i * _row_len]; } // read all data while (!cfeof(_cfp)) { _process_chunk(); } // should be at EOF; attach to _frame_offsets to make next_frame code simpler Assertion(cfeof(_cfp) != 0, "apng not at EOF, get a coder!"); _frame_offsets.push_back(cftell(_cfp)); // sanity checks if (anim_time <= 0.0f) { _apng_failed("animation duration <= 0.0f, bad data?"); } if (nframes < 1) { _apng_failed("animation didn't have any frames, is this a static png?"); } // back to start, including reset of _cfp so it can be used for the 1st frame _reading = false; if (cfseek(_cfp, _frame_offsets.at(0), CF_SEEK_SET) != 0) { _apng_failed("couldn't seek to 1st fcTL offset"); } return PNG_ERROR_NONE; }