Repository: sz3/libcimbar
File: src/lib/cimb_translator/CimbReader.cpp (C++)

Code before:
	}

	bool simpleColorCorrection(const cv::Mat& img, CimbDecoder& decoder)
	{
		std::tuple<float, float, float> white = calculateWhite(img, Config::dark());
		decoder.update_color_correction(color_correction::get_adaptation_matrix<adaptation_transform::von_kries>(white, {255.0, 255.0, 255.0}));
		return true;
	}

	// we will always skip the last unaltered block of a file
	// if it does not exactly match the chunk size
	// -- specifically, the encoder will skip *any* block that does not
	// match, but it so happens that it's only ever that one block.
	unsigned computeRadioactiveBlockId(const FountainMetadata& md, unsigned chunk_size)
	{
		if (md.file_size() % chunk_size == 0)
			return 0xFFFFFFFF; // there isn't one
		return md.file_size() / chunk_size;
	}
}

CimbReader::CimbReader(const cv::Mat& img, CimbDecoder& decoder, unsigned color_mode, bool needs_sharpen, int color_correction)
	: _image(img)
	, _fountainColorHeader(0U)
	, _radioactiveBlockId(0) // can only compute once we know the file size
	, _cellSize(Config::cell_size() + 2)
	, _positions(
		  cimbar::vec_xy{Config::cell_spacing_x(), Config::cell_spacing_y()},
		  cimbar::vec_xy{Config::cells_per_col_x(), Config::cells_per_col_y()},
		  Config::cell_offset(), cimbar::vec_xy{Config::corner_padding_x(), Config::corner_padding_y()}
	)
	, _decoder(decoder)
	, _good(_image.cols >= Config::image_size_x() and _image.rows >= Config::image_size_y())
	, _colorCorrection(color_correction)
	, _colorMode(color_mode)
{
	_grayscale = preprocessSymbolGrid(img, needs_sharpen);
	if (_good and color_correction == 1)
		simpleColorCorrection(_image, decoder);
}

CimbReader::CimbReader(const cv::UMat& img, CimbDecoder& decoder, unsigned color_mode, bool needs_sharpen, int color_correction)
	: CimbReader(img.getMat(cv::ACCESS_READ), decoder, color_mode, needs_sharpen, color_correction)
{
}

unsigned CimbReader::read_color(const PositionData& pos) const
{
	Cell color_cell(_image, pos.x, pos.y, Config::cell_size(), Config::cell_size());
	return _decoder.decode_color(color_cell, _colorMode);
}

Review comment (refactor):
One nice(?) thing about this change is that we have the CimbReader (concerned with post-extract images) intelligently figure out the padding. Which in turn means it can now accept non-exact image sizes -- although the image still needs to be centered to work.

Code after:

	bool simpleColorCorrection(const cv::Mat& img, CimbDecoder& decoder, unsigned padding)
	{
		std::tuple<float, float, float> white = calculateWhite(img, padding, Config::dark());
		decoder.update_color_correction(color_correction::get_adaptation_matrix<adaptation_transform::von_kries>(white, {255.0, 255.0, 255.0}));
		return true;
	}

	// we will always skip the last unaltered block of a file
	// if it does not exactly match the chunk size
	// -- specifically, the encoder will skip *any* block that does not
	// match, but it so happens that it's only ever that one block.
	unsigned computeRadioactiveBlockId(const FountainMetadata& md, unsigned chunk_size)
	{
		if (md.file_size() % chunk_size == 0)
			return 0xFFFFFFFF; // there isn't one
		return md.file_size() / chunk_size;
	}
}

CimbReader::CimbReader(const cv::Mat& img, CimbDecoder& decoder, unsigned color_mode, bool needs_sharpen, int color_correction)
	: _image(img)
	, _fountainColorHeader(0U)
	, _radioactiveBlockId(0) // can only compute once we know the file size
	, _cellSize(Config::cell_size() + 2)
	, _gridPadding(std::min(_image.cols - Config::image_size_x(), _image.rows - Config::image_size_y())/2)
	, _positions(
		  cimbar::vec_xy{Config::cell_spacing_x(), Config::cell_spacing_y()},
		  cimbar::vec_xy{Config::cells_per_col_x(), Config::cells_per_col_y()},
		  Config::cell_offset()+_gridPadding, cimbar::vec_xy{Config::corner_padding_x(), Config::corner_padding_y()}
	)
	, _decoder(decoder)
	, _good(_image.cols >= Config::image_size_x() and _image.rows >= Config::image_size_y())
	, _colorCorrection(color_correction)
	, _colorMode(color_mode)
{
	_grayscale = preprocessSymbolGrid(img, needs_sharpen);
	if (_good and color_correction == 1)
		simpleColorCorrection(_image, decoder, _gridPadding);
}

CimbReader::CimbReader(const cv::UMat& img, CimbDecoder& decoder, unsigned color_mode, bool needs_sharpen, int color_correction)
	: CimbReader(img.getMat(cv::ACCESS_READ), decoder, color_mode, needs_sharpen, color_correction)
{
}

unsigned CimbReader::read_color(const PositionData& pos) const
{
	Cell color_cell(_image, pos.x, pos.y, Config::cell_size(), Config::cell_size());
	return _decoder.decode_color(color_cell, _colorMode);
}