Example #1
0
/*
 * @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;
}
Example #2
0
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;
	}
}
Example #3
0
/*
 * @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;
}