in source/isp/CameraIsp.h [766:834]
void loadImageFromSensor(const std::vector<T>& inputImage) {
// - sanity check config
CHECK_NE(sensorWidth, 0);
CHECK_NE(sensorHeight, 0);
CHECK_EQ(sensorWidth % 2, 0);
CHECK_EQ(sensorHeight % 2, 0);
CHECK_EQ(inputImage.size(), sensorWidth * sensorHeight);
CHECK_EQ(sensorBitsPerPixel, 8 * sizeof(T));
cv::Mat_<T> intermediateImage(sensorHeight, sensorWidth);
// - load directly if there's nothing to do
if (!isPlanar && isLittleEndian == folly::kIsLittleEndian && isRowMajor) {
memcpy(intermediateImage.data, inputImage.data(), sensorWidth * sensorHeight * sizeof(T));
loadImage(intermediateImage);
return;
}
// - setup problem dimensions and channel mappings
int planeWidth = sensorWidth / 2;
int planeHeight = sensorHeight / 2;
int numPixelsPerPlane = planeWidth * planeHeight;
std::array<int, 4> inputChannelOrderToBayerOrder = {
{0, 1, 2, 3}}; // no-op for interleaved input
if (isPlanar) {
inputChannelOrderToBayerOrder = getPlaneOrderToBayerOrder();
}
// - inner loop helpers to byte swap, interleave, and re-index as needed
// - converts from linear index to a representation-independent (channel, row, column)
// pixel index
auto pixelIndexFromInputLinearIndex = [=](int linearIndex) {
int channel, row, col;
if (isPlanar) {
channel = linearIndex / numPixelsPerPlane;
int linearIndexInPlane = linearIndex - channel * numPixelsPerPlane;
std::tie(row, col) =
math_util::linearToMatrixIndex(linearIndexInPlane, planeHeight, planeWidth, isRowMajor);
} else {
std::tie(row, col) =
math_util::linearToMatrixIndex(linearIndex, sensorHeight, sensorWidth, isRowMajor);
// Bayer pattern is always specified in row major, so compute the channel index accordingly
channel = math_util::matrixToLinearIndex(std::make_tuple(row % 2, col % 2), 2, 2);
row /= 2;
col /= 2;
}
return std::make_tuple(channel, row, col);
};
// - converts representation-independent (channel, row, column) pixel index to (row, column)
// matrix index in interleaved image
auto outputInterleavedRawIndexFromPixelIndex = [=](std::tuple<int, int, int> pixelIndex) {
int channel, row, col, bayerRow, bayerCol;
std::tie(channel, row, col) = pixelIndex;
channel = inputChannelOrderToBayerOrder[channel];
std::tie(bayerRow, bayerCol) = math_util::linearToMatrixIndex(channel, 2, 2);
return std::make_pair(2 * row + bayerRow, 2 * col + bayerCol);
};
auto byteSwap = isLittleEndian ? folly::Endian::little<T> : folly::Endian::big<T>;
// - reorder and load image
for (int k = 0; k < sensorWidth * sensorHeight; ++k) {
auto pixelIndex = pixelIndexFromInputLinearIndex(k);
auto rawIndex = outputInterleavedRawIndexFromPixelIndex(pixelIndex);
intermediateImage(std::get<0>(rawIndex), std::get<1>(rawIndex)) = byteSwap(inputImage[k]);
}
loadImage(intermediateImage);
}