Repository: sz3/libcimbar
File: src/lib/encoder/Decoder.h (C/C++)

Code before:
		unsigned bits = reader.read(pos);

		unsigned bitPos = interleaveLookup[pos.i] * _bitsPerOp;
		bb.write(bits, bitPos, _bitsPerOp);

		colorPositions[pos.i] = {bitPos, pos.x, pos.y};
	}

	// then decode colors.
	// the symbol+color decode could be done as one pass, but doing it as two gives us better cache utilization
	for (const PositionData& p : colorPositions)
	{
		unsigned bits = reader.read_color(p);
		bb.write(bits, p.i, _colorBits);
	}

	reed_solomon_stream rss(ostream, _eccBytes, _eccBlockSize);
	return bb.flush(rss);
}

template <typename MAT, typename STREAM>
inline unsigned Decoder::decode(const MAT& img, STREAM& ostream, unsigned color_mode, bool should_preprocess, int color_correction)
{
	CimbReader reader(img, _decoder, color_mode, should_preprocess, color_correction);
	return do_decode(reader, ostream, color_mode==0);
}

template <typename MAT, typename FOUNTAINSTREAM>
inline unsigned Decoder::decode_fountain(const MAT& img, FOUNTAINSTREAM& ostream,  unsigned color_mode, bool should_preprocess, int color_correction)
{
	CimbReader reader(img, _decoder, color_mode, should_preprocess, color_correction);
	aligned_stream aligner(ostream, ostream.chunk_size(), 0, std::bind(&CimbReader::update_metadata, &reader, std::placeholders::_1, std::placeholders::_2));
	return do_decode(reader, aligner, color_mode==0);
}

inline unsigned Decoder::decode(std::string filename, std::string output, unsigned color_mode)
{
	cv::Mat img = cv::imread(filename);
	cv::cvtColor(img, img, cv::COLOR_BGR2RGB);

	std::ofstream f(output);
	return decode(img, f, color_mode, false);
}

inline bool Decoder::load_ccm(std::string filename)
{
	File f(filename);
	std::string data = f.read_all();
	if (data.size() < 3*3*4)
		return false;


Review comment (suggestion):
This `color_mode==0` check is what determines where we do the "coupled" decode -- I don't think it *really* makes sense to lock them together that way long term, so this is something that will hopefully be addressed by future changes to the way runtime configuration is done.

Code after:
		PositionData pos;
		unsigned bits = reader.read(pos);

		unsigned bitPos = interleaveLookup[pos.i] * _bitsPerOp;
		bb.write(bits, bitPos, _bitsPerOp);

		colorPositions[pos.i] = {bitPos, pos.x, pos.y};
	}

	// then decode colors.
	// the symbol+color decode could be done as one pass, but doing it as two gives us better cache utilization
	for (const PositionData& p : colorPositions)
	{
		unsigned bits = reader.read_color(p);
		bb.write(bits, p.i, _colorBits);
	}

	reed_solomon_stream rss(ostream, _eccBytes, _eccBlockSize);
	return bb.flush(rss);
}

template <typename MAT, typename STREAM>
inline unsigned Decoder::decode(const MAT& img, STREAM& ostream, unsigned color_mode, bool should_preprocess, int color_correction)
{
	CimbReader reader(img, _decoder, color_mode, should_preprocess, color_correction);
	return do_decode(reader, ostream, color_mode==0);
}

template <typename MAT, typename FOUNTAINSTREAM>
inline unsigned Decoder::decode_fountain(const MAT& img, FOUNTAINSTREAM& ostream,  unsigned color_mode, bool should_preprocess, int color_correction)
{
	CimbReader reader(img, _decoder, color_mode, should_preprocess, color_correction);
	bool legacy_mode = color_mode == 0;
	unsigned chunk_size = cimbar::Config::fountain_chunk_size(_eccBytes, _bitsPerOp, legacy_mode);
	auto update_md_fun = std::bind(&CimbReader::update_metadata, &reader, std::placeholders::_1, std::placeholders::_2);

	// we don't want to feed the fountain stream bad data, so we eat the decode if we have a mismatch
	// we still might succeed the decode, in which case (hopefully) the positive bytes we return will
	// tell our caller to fix the underlying ostream so the next round will work.
	if (ostream.chunk_size() != chunk_size)
	{
		null_stream devnull;
		aligned_stream aligner(devnull, chunk_size, 0, update_md_fun);
		return do_decode(reader, aligner, legacy_mode);
	}

	aligned_stream aligner(ostream, ostream.chunk_size(), 0, update_md_fun);
	return do_decode(reader, aligner, legacy_mode);
}

inline unsigned Decoder::decode(std::string filename, std::string output, unsigned color_mode)